From b7d9fb76fd70bda9ebb99f8e284b5131ec132588 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 21 Nov 2023 17:54:36 +0100 Subject: [PATCH 01/24] use full color for branch icon background --- openpype/style/style.css | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/openpype/style/style.css b/openpype/style/style.css index ca368f84f8..f6ecebd683 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -512,52 +512,58 @@ QAbstractItemView::item:selected:hover { } /* Row colors (alternate colors) are from left - right */ -QAbstractItemView:branch { - background: transparent; +QTreeView::branch { + background: {color:bg-view}; +} +QTreeView::branch:hover { + background: {color:bg-view}; +} +QTreeView::branch:selected { + background: {color:bg-view}; } QAbstractItemView::branch:open:has-children:!has-siblings, QAbstractItemView::branch:open:has-children:has-siblings { border-image: none; image: url(:/openpype/images/branch_open.png); - background: transparent; + background: {color:bg-view}; } QAbstractItemView::branch:open:has-children:!has-siblings:hover, QAbstractItemView::branch:open:has-children:has-siblings:hover { border-image: none; image: url(:/openpype/images/branch_open_on.png); - background: transparent; + background: {color:bg-view}; } QAbstractItemView::branch:has-children:!has-siblings:closed, QAbstractItemView::branch:closed:has-children:has-siblings { border-image: none; image: url(:/openpype/images/branch_closed.png); - background: transparent; + background: {color:bg-view}; } QAbstractItemView::branch:has-children:!has-siblings:closed:hover, QAbstractItemView::branch:closed:has-children:has-siblings:hover { border-image: none; image: url(:/openpype/images/branch_closed_on.png); - background: transparent; + background: {color:bg-view}; } QAbstractItemView::branch:has-siblings:!adjoins-item { border-image: none; image: url(:/openpype/images/transparent.png); - background: transparent; + background: {color:bg-view}; } QAbstractItemView::branch:has-siblings:adjoins-item { border-image: none; image: url(:/openpype/images/transparent.png); - background: transparent; + background: {color:bg-view}; } QAbstractItemView::branch:!has-children:!has-siblings:adjoins-item { border-image: none; image: url(:/openpype/images/transparent.png); - background: transparent; + background: {color:bg-view}; } CompleterView { From 12417e1ffa6edf8ca4b49f7b746eec165f58fc72 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Nov 2023 22:55:44 +0800 Subject: [PATCH 02/24] make sure resolution with burnin are correct --- openpype/hosts/max/api/preview_animation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index 6c7b8eaa80..74579b165f 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -198,8 +198,8 @@ def _render_preview_animation_max_pre_2024( res_width, res_height, filename=filepath ) dib = rt.gw.getViewportDib() - dib_width = rt.renderWidth - dib_height = rt.renderHeight + dib_width = float(dib.width) + dib_height = float(dib.height) # aspect ratio viewportRatio = dib_width / dib_height renderRatio = float(res_width / res_height) From 3bc341b8ba5d877db9e9cb8a3c9eb616d1f21636 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 5 Dec 2023 22:01:18 +0800 Subject: [PATCH 03/24] make sure the processEvents not rushing into indefinite loop --- openpype/hosts/substancepainter/api/lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/substancepainter/api/lib.py b/openpype/hosts/substancepainter/api/lib.py index 2cd08f862e..7055c1f8ba 100644 --- a/openpype/hosts/substancepainter/api/lib.py +++ b/openpype/hosts/substancepainter/api/lib.py @@ -588,6 +588,7 @@ def prompt_new_file_with_mesh(mesh_filepath): # the file while not file_dialog.selectedFiles(): app.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents, 1000) + continue print(f"Selected: {file_dialog.selectedFiles()}") # Set it again now we know the path is refreshed - without this From 72d86c4e0dd99041b7f3a3b618b40bdfb1cef558 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 6 Dec 2023 21:12:30 +0800 Subject: [PATCH 04/24] add missing repair action in validate resolution setting --- .../max/plugins/publish/validate_resolution_setting.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_resolution_setting.py b/openpype/hosts/max/plugins/publish/validate_resolution_setting.py index 7d91a7b991..1c4b05c556 100644 --- a/openpype/hosts/max/plugins/publish/validate_resolution_setting.py +++ b/openpype/hosts/max/plugins/publish/validate_resolution_setting.py @@ -1,9 +1,12 @@ import pyblish.api +from pymxs import runtime as rt from openpype.pipeline import ( - PublishValidationError, OptionalPyblishPluginMixin ) -from pymxs import runtime as rt +from openpype.pipeline.publish import ( + RepairAction, + PublishValidationError +) from openpype.hosts.max.api.lib import reset_scene_resolution @@ -16,6 +19,7 @@ class ValidateResolutionSetting(pyblish.api.InstancePlugin, hosts = ["max"] label = "Validate Resolution Setting" optional = True + actions = [RepairAction] def process(self, instance): if not self.is_active(instance.data): From 7c104e1336984071cbd341e4e4938421c094b54e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 6 Dec 2023 22:28:35 +0800 Subject: [PATCH 05/24] make sure the select file dialog is closed after selecting the mesh file and make sure the new project dialog hit accepted after finishing the mesh selection and other settings --- openpype/hosts/substancepainter/api/lib.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/openpype/hosts/substancepainter/api/lib.py b/openpype/hosts/substancepainter/api/lib.py index 7055c1f8ba..71b7e3630a 100644 --- a/openpype/hosts/substancepainter/api/lib.py +++ b/openpype/hosts/substancepainter/api/lib.py @@ -583,21 +583,7 @@ def prompt_new_file_with_mesh(mesh_filepath): file_dialog.setDirectory(os.path.dirname(mesh_filepath)) url = QtCore.QUrl.fromLocalFile(os.path.basename(mesh_filepath)) file_dialog.selectUrl(url) - - # Give the explorer window time to refresh to the folder and select - # the file - while not file_dialog.selectedFiles(): - app.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents, 1000) - continue - print(f"Selected: {file_dialog.selectedFiles()}") - - # Set it again now we know the path is refreshed - without this - # accepting the dialog will often not trigger the correct filepath - file_dialog.setDirectory(os.path.dirname(mesh_filepath)) - url = QtCore.QUrl.fromLocalFile(os.path.basename(mesh_filepath)) - file_dialog.selectUrl(url) - - file_dialog.done(file_dialog.Accepted) + file_dialog.close() app.processEvents(QtCore.QEventLoop.AllEvents) def _setup_prompt(): @@ -630,6 +616,8 @@ def prompt_new_file_with_mesh(mesh_filepath): if not mesh_filename_label.text(): dialog.close() raise RuntimeError(f"Failed to set mesh path: {mesh_filepath}") + else: + dialog.done(dialog.Accepted) new_action = _get_new_project_action() if not new_action: From e88b692d2acd44b686bec7e6759892ca1404b94a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 11:57:50 +0800 Subject: [PATCH 06/24] add the processEvents after the dialog has selected the file URL --- openpype/hosts/substancepainter/api/lib.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/substancepainter/api/lib.py b/openpype/hosts/substancepainter/api/lib.py index 71b7e3630a..bb4481bb1d 100644 --- a/openpype/hosts/substancepainter/api/lib.py +++ b/openpype/hosts/substancepainter/api/lib.py @@ -583,7 +583,9 @@ def prompt_new_file_with_mesh(mesh_filepath): file_dialog.setDirectory(os.path.dirname(mesh_filepath)) url = QtCore.QUrl.fromLocalFile(os.path.basename(mesh_filepath)) file_dialog.selectUrl(url) - file_dialog.close() + app.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents, 3000) + + file_dialog.done(file_dialog.Accepted) app.processEvents(QtCore.QEventLoop.AllEvents) def _setup_prompt(): From 459000ec90fa3cdcd11608c4085a620844f5e0c9 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 18:28:28 +0800 Subject: [PATCH 07/24] if the prompt dialog can't help to import mesh, use substance_painter.project.create instead to 'load' the mesh into the scene --- .../hosts/substancepainter/plugins/load/load_mesh.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/substancepainter/plugins/load/load_mesh.py b/openpype/hosts/substancepainter/plugins/load/load_mesh.py index 57db869a11..ca22163c5d 100644 --- a/openpype/hosts/substancepainter/plugins/load/load_mesh.py +++ b/openpype/hosts/substancepainter/plugins/load/load_mesh.py @@ -44,14 +44,20 @@ class SubstanceLoadProjectMesh(load.LoaderPlugin): # Get user inputs import_cameras = data.get("import_cameras", True) preserve_strokes = data.get("preserve_strokes", True) - + sp_settings = substance_painter.project.Settings( + import_cameras=import_cameras + ) if not substance_painter.project.is_open(): # Allow to 'initialize' a new project path = self.filepath_from_context(context) result = prompt_new_file_with_mesh(mesh_filepath=path) if not result: - self.log.info("User cancelled new project prompt.") - return + self.log.info("User cancelled new project prompt." + "Creating new project directly from" + " Substance Painter API Instead.") + settings = substance_painter.project.create( + mesh_file_path=path, settings=sp_settings + ) else: # Reload the mesh From aeaee28539a2903eb2fb061e14ab673204f2a11b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 18:51:07 +0800 Subject: [PATCH 08/24] edit the comment --- openpype/hosts/substancepainter/api/lib.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/substancepainter/api/lib.py b/openpype/hosts/substancepainter/api/lib.py index bb4481bb1d..35e5b63625 100644 --- a/openpype/hosts/substancepainter/api/lib.py +++ b/openpype/hosts/substancepainter/api/lib.py @@ -617,7 +617,9 @@ def prompt_new_file_with_mesh(mesh_filepath): mesh_filename_label = mesh_filename.findChild(QtWidgets.QLabel) if not mesh_filename_label.text(): dialog.close() - raise RuntimeError(f"Failed to set mesh path: {mesh_filepath}") + substance_painter.logging.warning( + f"Failed to set mesh path with the prompt dialog: {mesh_filepath}\n\n" + "Creating new project directly with the mesh path instead.") else: dialog.done(dialog.Accepted) From 34bb371b810ca0c12ff99729cfb9d045aaa1bdeb Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 18:53:04 +0800 Subject: [PATCH 09/24] hound --- openpype/hosts/substancepainter/api/lib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/substancepainter/api/lib.py b/openpype/hosts/substancepainter/api/lib.py index 35e5b63625..4d3a1d19bd 100644 --- a/openpype/hosts/substancepainter/api/lib.py +++ b/openpype/hosts/substancepainter/api/lib.py @@ -618,7 +618,8 @@ def prompt_new_file_with_mesh(mesh_filepath): if not mesh_filename_label.text(): dialog.close() substance_painter.logging.warning( - f"Failed to set mesh path with the prompt dialog: {mesh_filepath}\n\n" + "Failed to set mesh path with the prompt dialog:" + f"{mesh_filepath}\n\n" "Creating new project directly with the mesh path instead.") else: dialog.done(dialog.Accepted) From f0692c87777f9bd31f73a48d3731c54f0f46c1d0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 20:53:53 +0800 Subject: [PATCH 10/24] add comment --- openpype/hosts/substancepainter/api/lib.py | 2 ++ openpype/hosts/substancepainter/plugins/load/load_mesh.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/openpype/hosts/substancepainter/api/lib.py b/openpype/hosts/substancepainter/api/lib.py index 4d3a1d19bd..1cb480b552 100644 --- a/openpype/hosts/substancepainter/api/lib.py +++ b/openpype/hosts/substancepainter/api/lib.py @@ -583,6 +583,8 @@ def prompt_new_file_with_mesh(mesh_filepath): file_dialog.setDirectory(os.path.dirname(mesh_filepath)) url = QtCore.QUrl.fromLocalFile(os.path.basename(mesh_filepath)) file_dialog.selectUrl(url) + # TODO: find a way to improve the process event to + # load more complicated mesh app.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents, 3000) file_dialog.done(file_dialog.Accepted) diff --git a/openpype/hosts/substancepainter/plugins/load/load_mesh.py b/openpype/hosts/substancepainter/plugins/load/load_mesh.py index ca22163c5d..6b4b79753b 100644 --- a/openpype/hosts/substancepainter/plugins/load/load_mesh.py +++ b/openpype/hosts/substancepainter/plugins/load/load_mesh.py @@ -50,6 +50,8 @@ class SubstanceLoadProjectMesh(load.LoaderPlugin): if not substance_painter.project.is_open(): # Allow to 'initialize' a new project path = self.filepath_from_context(context) + #TODO: improve the prompt dialog function to not + # only works for simple polygon scene result = prompt_new_file_with_mesh(mesh_filepath=path) if not result: self.log.info("User cancelled new project prompt." From 16c7d5565d072d84d9a1f5e717c54b832431b7fc Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 20:54:35 +0800 Subject: [PATCH 11/24] hound --- openpype/hosts/substancepainter/plugins/load/load_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/substancepainter/plugins/load/load_mesh.py b/openpype/hosts/substancepainter/plugins/load/load_mesh.py index 6b4b79753b..08c1d5c391 100644 --- a/openpype/hosts/substancepainter/plugins/load/load_mesh.py +++ b/openpype/hosts/substancepainter/plugins/load/load_mesh.py @@ -50,7 +50,7 @@ class SubstanceLoadProjectMesh(load.LoaderPlugin): if not substance_painter.project.is_open(): # Allow to 'initialize' a new project path = self.filepath_from_context(context) - #TODO: improve the prompt dialog function to not + # TODO: improve the prompt dialog function to not # only works for simple polygon scene result = prompt_new_file_with_mesh(mesh_filepath=path) if not result: From 8a1a1c3b15790859985c1120764b8a1dd32e91c3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 9 Dec 2023 03:26:34 +0000 Subject: [PATCH 12/24] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f827d275a6..6f651076ce 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to OpenPype Tray options: + - 3.17.7-nightly.7 - 3.17.7-nightly.6 - 3.17.7-nightly.5 - 3.17.7-nightly.4 @@ -134,7 +135,6 @@ body: - 3.15.3-nightly.3 - 3.15.3-nightly.2 - 3.15.3-nightly.1 - - 3.15.2 validations: required: true - type: dropdown From 97b192b02bd6639d9740da8a17540af804d76f1a Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 11 Dec 2023 12:50:09 +0200 Subject: [PATCH 13/24] remove redundant code --- .../houdini/plugins/publish/collect_chunk_size.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/collect_chunk_size.py b/openpype/hosts/houdini/plugins/publish/collect_chunk_size.py index 1c867e930a..f8cd4089e2 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_chunk_size.py +++ b/openpype/hosts/houdini/plugins/publish/collect_chunk_size.py @@ -14,18 +14,13 @@ class CollectChunkSize(pyblish.api.InstancePlugin, hosts = ["houdini"] targets = ["local", "remote"] label = "Collect Chunk Size" - chunkSize = 999999 + chunk_size = 999999 def process(self, instance): # need to get the chunk size info from the setting attr_values = self.get_attr_values_from_data(instance.data) instance.data["chunkSize"] = attr_values.get("chunkSize") - @classmethod - def apply_settings(cls, project_settings): - project_setting = project_settings["houdini"]["publish"]["CollectChunkSize"] # noqa - cls.chunkSize = project_setting["chunk_size"] - @classmethod def get_attribute_defs(cls): return [ @@ -33,7 +28,6 @@ class CollectChunkSize(pyblish.api.InstancePlugin, minimum=1, maximum=999999, decimals=0, - default=cls.chunkSize, + default=cls.chunk_size, label="Frame Per Task") - ] From 3de0c8ed66c521119d8847df19735fec86bcb143 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 11 Dec 2023 12:50:47 +0200 Subject: [PATCH 14/24] add missing settings --- .../defaults/project_settings/houdini.json | 12 +++-- .../schemas/schema_houdini_create.json | 4 ++ .../schemas/schema_houdini_publish.json | 50 +++++++++---------- .../houdini/server/settings/create.py | 7 +++ .../houdini/server/settings/publish.py | 17 +++++++ 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index 0001b23967..813e7153ea 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -62,6 +62,12 @@ "Main" ] }, + "CreateMantraIFD": { + "enabled": true, + "default_variants": [ + "Main" + ] + }, "CreateMantraROP": { "enabled": true, "default_variants": [ @@ -137,14 +143,14 @@ } }, "publish": { + "CollectAssetHandles": { + "use_asset_handles": true + }, "CollectChunkSize": { "enabled": true, "optional": true, "chunk_size": 999999 }, - "CollectAssetHandles": { - "use_asset_handles": true - }, "ValidateContainers": { "enabled": true, "optional": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json index f37738c4ec..213ec9d04e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json @@ -69,6 +69,10 @@ "key": "CreateKarmaROP", "label": "Create Karma ROP" }, + { + "key": "CreateMantraIFD", + "label": "Create Mantra IFD" + }, { "key": "CreateMantraROP", "label": "Create Mantra ROP" diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json index 935c2a4c35..aaaf4311b7 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_publish.json @@ -25,6 +25,31 @@ } ] }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "CollectChunkSize", + "label": "Collect Chunk Size", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "number", + "key": "chunk_size", + "label": "Frames Per Task" + } + ] + }, { "type": "label", "label": "Validators" @@ -55,31 +80,6 @@ } ] }, - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "CollectChunkSize", - "label": "Collect Chunk Size", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "number", - "key": "chunk_size", - "label": "Frames Per Task" - } - ] - }, { "type": "dict", "collapsible": true, diff --git a/server_addon/houdini/server/settings/create.py b/server_addon/houdini/server/settings/create.py index e8db917849..a5ca4d477b 100644 --- a/server_addon/houdini/server/settings/create.py +++ b/server_addon/houdini/server/settings/create.py @@ -52,6 +52,9 @@ class CreatePluginsModel(BaseSettingsModel): CreateKarmaROP: CreatorModel = Field( default_factory=CreatorModel, title="Create Karma ROP") + CreateMantraIFD: CreatorModel = Field( + default_factory=CreatorModel, + title="Create Mantra IFD") CreateMantraROP: CreatorModel = Field( default_factory=CreatorModel, title="Create Mantra ROP") @@ -114,6 +117,10 @@ DEFAULT_HOUDINI_CREATE_SETTINGS = { "enabled": True, "default_variants": ["Main"] }, + "CreateMantraIFD": { + "enabled": True, + "default_variants": ["Main"] + }, "CreateMantraROP": { "enabled": True, "default_variants": ["Main"] diff --git a/server_addon/houdini/server/settings/publish.py b/server_addon/houdini/server/settings/publish.py index 92a676b0d0..692c7b2fa0 100644 --- a/server_addon/houdini/server/settings/publish.py +++ b/server_addon/houdini/server/settings/publish.py @@ -13,6 +13,14 @@ class CollectAssetHandlesModel(BaseSettingsModel): title="Use asset handles") +class CollectChunkSizeModel(BaseSettingsModel): + """Collect Chunk Size.""" + enabled: bool = Field(title="Enabled") + optional: bool = Field(title="Optional") + chunk_size: int = Field( + title="Frames Per Task") + + class ValidateWorkfilePathsModel(BaseSettingsModel): enabled: bool = Field(title="Enabled") optional: bool = Field(title="Optional") @@ -38,6 +46,10 @@ class PublishPluginsModel(BaseSettingsModel): title="Collect Asset Handles.", section="Collectors" ) + CollectChunkSize: CollectChunkSizeModel = Field( + default_factory=CollectChunkSizeModel, + title="Collect Chunk Size." + ) ValidateContainers: BasicValidateModel = Field( default_factory=BasicValidateModel, title="Validate Latest Containers.", @@ -63,6 +75,11 @@ DEFAULT_HOUDINI_PUBLISH_SETTINGS = { "CollectAssetHandles": { "use_asset_handles": True }, + "CollectChunkSize" : { + "enabled": True, + "optional": True, + "chunk_size": 999999 + }, "ValidateContainers": { "enabled": True, "optional": True, From b6291e2b6721d7bfdc63d9eccff6e84c54fa714f Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 11 Dec 2023 12:51:08 +0200 Subject: [PATCH 15/24] bump houdini addon patch version --- server_addon/houdini/server/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/houdini/server/version.py b/server_addon/houdini/server/version.py index 75cf7831c4..6232f7ab18 100644 --- a/server_addon/houdini/server/version.py +++ b/server_addon/houdini/server/version.py @@ -1 +1 @@ -__version__ = "0.2.9" +__version__ = "0.2.10" From 69ed6f5d20a685f8cf94f58e9a6c926b23d13262 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Mon, 11 Dec 2023 13:00:32 +0200 Subject: [PATCH 16/24] resolve hound - Remove redundant white space --- server_addon/houdini/server/settings/publish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/houdini/server/settings/publish.py b/server_addon/houdini/server/settings/publish.py index 692c7b2fa0..f551b3a209 100644 --- a/server_addon/houdini/server/settings/publish.py +++ b/server_addon/houdini/server/settings/publish.py @@ -75,7 +75,7 @@ DEFAULT_HOUDINI_PUBLISH_SETTINGS = { "CollectAssetHandles": { "use_asset_handles": True }, - "CollectChunkSize" : { + "CollectChunkSize": { "enabled": True, "optional": True, "chunk_size": 999999 From 6d36857fe8026f793d30cabc15bb5e1d432e3570 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 11 Dec 2023 11:19:43 +0000 Subject: [PATCH 17/24] Testing: Validate errors and failed status from Deadline jobs. (#5986) * Validate errors from Deadline jobs. * Check dependency chain and failed jobs. * Houd * Fix wrong datatype It failed on expecting string but receiving dictionary. --------- Co-authored-by: kalisp --- tests/lib/testing_classes.py | 57 +++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/lib/testing_classes.py b/tests/lib/testing_classes.py index 7a90f76662..ade38d60c8 100644 --- a/tests/lib/testing_classes.py +++ b/tests/lib/testing_classes.py @@ -481,7 +481,7 @@ class DeadlinePublishTest(PublishTest): while not valid_date_finished: time.sleep(0.5) if time.time() - time_start > timeout: - raise ValueError("Timeout for DL finish reached") + raise ValueError("Timeout for Deadline finish reached") response = requests.get(url, timeout=10) if not response.ok: @@ -491,6 +491,61 @@ class DeadlinePublishTest(PublishTest): if not response.json(): raise ValueError("Couldn't find {}".format(deadline_job_id)) + job = response.json()[0] + + def recursive_dependencies(job, results=None): + if results is None: + results = [] + + for dependency in job["Props"]["Dep"]: + dependency = requests.get( + "{}/api/jobs?JobId={}".format( + deadline_url, dependency["JobID"] + ), + timeout=10 + ).json()[0] + results.append(dependency) + grand_dependencies = recursive_dependencies( + dependency, results=results + ) + for grand_dependency in grand_dependencies: + if grand_dependency not in results: + results.append(grand_dependency) + return results + + job_status = { + 0: "Unknown", + 1: "Active", + 2: "Suspended", + 3: "Completed", + 4: "Failed", + 6: "Pending" + } + + jobs_to_validate = [job] + jobs_to_validate.extend(recursive_dependencies(job)) + failed_jobs = [] + errors = [] + for job in jobs_to_validate: + if "Failed" == job_status[job["Stat"]]: + failed_jobs.append(str(job)) + + resp_error = requests.get( + "{}/api/jobreports?JobID={}&Data=allerrorcontents".format( + deadline_url, job["_id"] + ), + timeout=10 + ) + errors.extend(resp_error.json()) + + msg = "Errors in Deadline:\n" + msg += "\n".join(errors) + assert not errors, msg + + msg = "Failed in Deadline:\n" + msg += "\n".join(failed_jobs) + assert not failed_jobs, msg + # '0001-...' returned until job is finished valid_date_finished = response.json()[0]["DateComp"][:4] != "0001" From 2d73f6a6aaa5e54134cf7b43dc4402609529cf06 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 11 Dec 2023 12:51:58 +0100 Subject: [PATCH 18/24] Chore: Staging mode determination (#5895) * use 'is_staging_enabled' to determine if staging resource is used * fix bug in 'is_running_staging' --- openpype/lib/openpype_version.py | 2 +- openpype/resources/__init__.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/lib/openpype_version.py b/openpype/lib/openpype_version.py index 1c8356d5fe..5618eb0c2e 100644 --- a/openpype/lib/openpype_version.py +++ b/openpype/lib/openpype_version.py @@ -140,7 +140,7 @@ def is_running_staging(): latest_version = get_latest_version(local=False, remote=True) staging_version = latest_version - if current_version == production_version: + if current_version == staging_version: return True return is_staging_enabled() diff --git a/openpype/resources/__init__.py b/openpype/resources/__init__.py index b33d1bf023..c429fb8c3e 100644 --- a/openpype/resources/__init__.py +++ b/openpype/resources/__init__.py @@ -1,6 +1,6 @@ import os from openpype import AYON_SERVER_ENABLED -from openpype.lib.openpype_version import is_running_staging +from openpype.lib.openpype_version import is_staging_enabled RESOURCES_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -59,7 +59,7 @@ def get_openpype_icon_filepath(staging=None): return get_resource("icons", "AYON_icon_dev.png") if staging is None: - staging = is_running_staging() + staging = is_staging_enabled() if staging: return get_openpype_staging_icon_filepath() @@ -68,7 +68,7 @@ def get_openpype_icon_filepath(staging=None): def get_openpype_splash_filepath(staging=None): if staging is None: - staging = is_running_staging() + staging = is_staging_enabled() if AYON_SERVER_ENABLED: if os.getenv("AYON_USE_DEV") == "1": From 72e980b1e493c185794900ff59dfcb9e888f838a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 11 Dec 2023 12:58:38 +0100 Subject: [PATCH 19/24] keys in hierarchyContext are always names --- .../standalonepublisher/plugins/publish/collect_hierarchy.py | 4 ++-- .../traypublisher/plugins/publish/collect_shot_instances.py | 4 ++-- openpype/plugins/publish/collect_hierarchy.py | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/standalonepublisher/plugins/publish/collect_hierarchy.py b/openpype/hosts/standalonepublisher/plugins/publish/collect_hierarchy.py index 9109bf6726..eb06875601 100644 --- a/openpype/hosts/standalonepublisher/plugins/publish/collect_hierarchy.py +++ b/openpype/hosts/standalonepublisher/plugins/publish/collect_hierarchy.py @@ -257,8 +257,6 @@ class CollectHierarchyContext(pyblish.api.ContextPlugin): if 'shot' not in instance.data.get('family', ''): continue - name = instance.data["asset"] - # get handles handle_start = int(instance.data["handleStart"]) handle_end = int(instance.data["handleEnd"]) @@ -286,6 +284,8 @@ class CollectHierarchyContext(pyblish.api.ContextPlugin): parents = instance.data.get('parents', []) self.log.debug(f"parents: {pformat(parents)}") + # Split by '/' for AYON where asset is a path + name = instance.data["asset"].split("/")[-1] actual = {name: in_info} for parent in reversed(parents): diff --git a/openpype/hosts/traypublisher/plugins/publish/collect_shot_instances.py b/openpype/hosts/traypublisher/plugins/publish/collect_shot_instances.py index e00ac64244..b99b634da1 100644 --- a/openpype/hosts/traypublisher/plugins/publish/collect_shot_instances.py +++ b/openpype/hosts/traypublisher/plugins/publish/collect_shot_instances.py @@ -155,8 +155,6 @@ class CollectShotInstance(pyblish.api.InstancePlugin): else {} ) - asset_name = instance.data["asset"] - # get handles handle_start = int(instance.data["handleStart"]) handle_end = int(instance.data["handleEnd"]) @@ -177,6 +175,8 @@ class CollectShotInstance(pyblish.api.InstancePlugin): parents = instance.data.get('parents', []) + # Split by '/' for AYON where asset is a path + asset_name = instance.data["asset"].split("/")[-1] actual = {asset_name: in_info} for parent in reversed(parents): diff --git a/openpype/plugins/publish/collect_hierarchy.py b/openpype/plugins/publish/collect_hierarchy.py index b5fd1e4bb9..32f10ba4c8 100644 --- a/openpype/plugins/publish/collect_hierarchy.py +++ b/openpype/plugins/publish/collect_hierarchy.py @@ -61,8 +61,9 @@ class CollectHierarchy(pyblish.api.ContextPlugin): "resolutionHeight": instance.data["resolutionHeight"], "pixelAspect": instance.data["pixelAspect"] } - - actual = {instance.data["asset"]: shot_data} + # Split by '/' for AYON where asset is a path + name = instance.data["asset"].split("/")[-1] + actual = {name: shot_data} for parent in reversed(instance.data["parents"]): next_dict = {} From 8a3a318480699e3f12866e0783973338c6bbfc05 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 11 Dec 2023 12:59:18 +0100 Subject: [PATCH 20/24] modify extract hierarchy to ayon to work with names --- .../publish/extract_hierarchy_to_ayon.py | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/openpype/plugins/publish/extract_hierarchy_to_ayon.py b/openpype/plugins/publish/extract_hierarchy_to_ayon.py index ef69369d67..8f791a6093 100644 --- a/openpype/plugins/publish/extract_hierarchy_to_ayon.py +++ b/openpype/plugins/publish/extract_hierarchy_to_ayon.py @@ -223,23 +223,24 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): valid_ids = set() hierarchy_queue = collections.deque() - hierarchy_queue.append((project_id, project_children_context)) + hierarchy_queue.append((project_id, "", project_children_context)) while hierarchy_queue: queue_item = hierarchy_queue.popleft() - parent_id, children_context = queue_item + parent_id, parent_path, children_context = queue_item if not children_context: continue - for asset, asset_info in children_context.items(): + for folder_name, folder_info in children_context.items(): + folder_path = "{}/{}".format(parent_path, folder_name) if ( - asset not in active_folder_paths - and not asset_info.get("childs") + folder_path not in active_folder_paths + and not folder_info.get("childs") ): continue - asset_name = asset.split("/")[-1] + item_id = uuid.uuid4().hex - new_item = copy.deepcopy(asset_info) - new_item["name"] = asset_name + new_item = copy.deepcopy(folder_info) + new_item["name"] = folder_name new_item["children"] = [] new_children_context = new_item.pop("childs", None) tasks = new_item.pop("tasks", {}) @@ -253,9 +254,11 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): items_by_id[item_id] = new_item parent_id_by_item_id[item_id] = parent_id - if asset in active_folder_paths: + if folder_path in active_folder_paths: valid_ids.add(item_id) - hierarchy_queue.append((item_id, new_children_context)) + hierarchy_queue.append( + (item_id, folder_path, new_children_context) + ) if not valid_ids: return None From c1cba8640fb7da4222acde29b8261c77e71aa65b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 11 Dec 2023 15:52:12 +0100 Subject: [PATCH 21/24] convert the createAt value to local timezone --- openpype/client/server/conversion_utils.py | 2 +- openpype/tools/ayon_loader/models/products.py | 2 +- openpype/tools/ayon_workfiles/models/workfiles.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/client/server/conversion_utils.py b/openpype/client/server/conversion_utils.py index 51af99e722..e8d3c4cbe4 100644 --- a/openpype/client/server/conversion_utils.py +++ b/openpype/client/server/conversion_utils.py @@ -606,7 +606,7 @@ def convert_v4_version_to_v3(version): output_data[dst_key] = version[src_key] if "createdAt" in version: - created_at = arrow.get(version["createdAt"]) + created_at = arrow.get(version["createdAt"]).to("local") output_data["time"] = created_at.strftime("%Y%m%dT%H%M%SZ") output["data"] = output_data diff --git a/openpype/tools/ayon_loader/models/products.py b/openpype/tools/ayon_loader/models/products.py index daa36aefdc..135f28df97 100644 --- a/openpype/tools/ayon_loader/models/products.py +++ b/openpype/tools/ayon_loader/models/products.py @@ -44,7 +44,7 @@ def version_item_from_entity(version): # NOTE There is also 'updatedAt', should be used that instead? # TODO skip conversion - converting to '%Y%m%dT%H%M%SZ' is because # 'PrettyTimeDelegate' expects it - created_at = arrow.get(version["createdAt"]) + created_at = arrow.get(version["createdAt"]).to("local") published_time = created_at.strftime("%Y%m%dT%H%M%SZ") author = version["author"] version_num = version["version"] diff --git a/openpype/tools/ayon_workfiles/models/workfiles.py b/openpype/tools/ayon_workfiles/models/workfiles.py index 907b9b5383..d74a8e164d 100644 --- a/openpype/tools/ayon_workfiles/models/workfiles.py +++ b/openpype/tools/ayon_workfiles/models/workfiles.py @@ -606,7 +606,7 @@ class PublishWorkfilesModel: print("Failed to format workfile path: {}".format(exc)) dirpath, filename = os.path.split(workfile_path) - created_at = arrow.get(repre_entity["createdAt"]) + created_at = arrow.get(repre_entity["createdAt"].to("local")) return FileItem( dirpath, filename, From d66bac0f145e39228804dace2f42190131ad4b68 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 11 Dec 2023 17:50:48 +0100 Subject: [PATCH 22/24] Tests: update after thumbnail default change (#6040) * Updates to tests because of default Thumbnail non integration Some previous PR changed default behavior of Thumbnail, they are not integrated anymore. Tests were expecting they are. Change in AE local render is required to match behavior and provide Colorspace handling. * Updates to tests because of default Thumbnail non integration Missed values * Updates to tests because of default Thumbnail non integration Missed values --- .../plugins/publish/extract_local_render.py | 5 +++-- .../test_deadline_publish_in_aftereffects.py | 4 ++-- ..._publish_in_aftereffects_multicomposition.py | 4 ++-- .../test_publish_in_aftereffects.py | 4 ++-- .../test_publish_in_aftereffects_legacy.py | 6 +++--- .../test_publish_in_aftereffects_multiframe.py | 4 ++-- .../hosts/maya/test_deadline_publish_in_maya.py | 4 ++-- ...st_asset_renderTest_taskMain_beauty_v001.jpg | Bin 77035 -> 0 bytes .../hosts/nuke/test_deadline_publish_in_nuke.py | 4 ++-- 9 files changed, 18 insertions(+), 17 deletions(-) delete mode 100644 tests/integration/hosts/maya/test_deadline_publish_in_maya/expected/test_project/test_asset/publish/render/renderTest_taskMain_beauty/v001/test_project_test_asset_renderTest_taskMain_beauty_v001.jpg diff --git a/openpype/hosts/aftereffects/plugins/publish/extract_local_render.py b/openpype/hosts/aftereffects/plugins/publish/extract_local_render.py index bdb48e11f8..b44e986d83 100644 --- a/openpype/hosts/aftereffects/plugins/publish/extract_local_render.py +++ b/openpype/hosts/aftereffects/plugins/publish/extract_local_render.py @@ -60,8 +60,9 @@ class ExtractLocalRender(publish.Extractor): first_repre = not representations if instance.data["review"] and first_repre: repre_data["tags"] = ["review"] - thumbnail_path = os.path.join(staging_dir, files[0]) - instance.data["thumbnailSource"] = thumbnail_path + # TODO return back when Extract from source same as regular + # thumbnail_path = os.path.join(staging_dir, files[0]) + # instance.data["thumbnailSource"] = thumbnail_path representations.append(repre_data) diff --git a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py index 30761693a8..1aa612207d 100644 --- a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py +++ b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py @@ -60,7 +60,7 @@ class TestDeadlinePublishInAfterEffects(AEDeadlinePublishTestClass): name="renderTest_taskMain")) failures.append( - DBAssert.count_of_types(dbcon, "representation", 4)) + DBAssert.count_of_types(dbcon, "representation", 3)) additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} @@ -77,7 +77,7 @@ class TestDeadlinePublishInAfterEffects(AEDeadlinePublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py index 0e9cd3b00d..4254b951b5 100644 --- a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py +++ b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py @@ -71,7 +71,7 @@ class TestDeadlinePublishInAfterEffectsMultiComposition(AEDeadlinePublishTestCla name="renderTest_taskMain2")) failures.append( - DBAssert.count_of_types(dbcon, "representation", 5)) + DBAssert.count_of_types(dbcon, "representation", 4)) additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} @@ -89,7 +89,7 @@ class TestDeadlinePublishInAfterEffectsMultiComposition(AEDeadlinePublishTestCla additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py index 2e4f343a5a..f13043d8bb 100644 --- a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py +++ b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py @@ -58,7 +58,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): name="renderTest_taskMain")) failures.append( - DBAssert.count_of_types(dbcon, "representation", 4)) + DBAssert.count_of_types(dbcon, "representation", 3)) additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} @@ -75,7 +75,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_legacy.py b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_legacy.py index a62036e4a7..b99db24e75 100644 --- a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_legacy.py +++ b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_legacy.py @@ -60,7 +60,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): name="renderTest_taskMain")) failures.append( - DBAssert.count_of_types(dbcon, "representation", 4)) + DBAssert.count_of_types(dbcon, "representation", 2)) additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} @@ -77,7 +77,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", @@ -89,7 +89,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py index dcf34844d1..bd9d3e9b50 100644 --- a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py +++ b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py @@ -45,7 +45,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): name="renderTest_taskMain")) failures.append( - DBAssert.count_of_types(dbcon, "representation", 4)) + DBAssert.count_of_types(dbcon, "representation", 3)) additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} @@ -62,7 +62,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/maya/test_deadline_publish_in_maya.py b/tests/integration/hosts/maya/test_deadline_publish_in_maya.py index 7d2b409db3..79d6c22a26 100644 --- a/tests/integration/hosts/maya/test_deadline_publish_in_maya.py +++ b/tests/integration/hosts/maya/test_deadline_publish_in_maya.py @@ -54,7 +54,7 @@ class TestDeadlinePublishInMaya(MayaDeadlinePublishTestClass): DBAssert.count_of_types(dbcon, "subset", 1, name="workfileTest_task")) - failures.append(DBAssert.count_of_types(dbcon, "representation", 8)) + failures.append(DBAssert.count_of_types(dbcon, "representation", 7)) # hero included additional_args = {"context.subset": "modelMain", @@ -85,7 +85,7 @@ class TestDeadlinePublishInMaya(MayaDeadlinePublishTestClass): additional_args = {"context.subset": "renderTest_taskMain_beauty", "context.ext": "jpg"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain_beauty", diff --git a/tests/integration/hosts/maya/test_deadline_publish_in_maya/expected/test_project/test_asset/publish/render/renderTest_taskMain_beauty/v001/test_project_test_asset_renderTest_taskMain_beauty_v001.jpg b/tests/integration/hosts/maya/test_deadline_publish_in_maya/expected/test_project/test_asset/publish/render/renderTest_taskMain_beauty/v001/test_project_test_asset_renderTest_taskMain_beauty_v001.jpg deleted file mode 100644 index 79ff799e8b063ba841c0566523d91de5c87a0c4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77035 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 diff --git a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py index a4026f195b..586078ead6 100644 --- a/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py +++ b/tests/integration/hosts/nuke/test_deadline_publish_in_nuke.py @@ -69,7 +69,7 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): name="workfileTest_task")) failures.append( - DBAssert.count_of_types(dbcon, "representation", 4)) + DBAssert.count_of_types(dbcon, "representation", 3)) additional_args = {"context.subset": "workfileTest_task", "context.ext": "nk"} @@ -86,7 +86,7 @@ class TestDeadlinePublishInNuke(NukeDeadlinePublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "name": "thumbnail"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 0, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", From ac49ab3803a993238eb77ed0eb04731bdeba8d52 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 12 Dec 2023 12:53:31 +0100 Subject: [PATCH 23/24] fill template data for editorial --- openpype/plugins/publish/collect_resources_path.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/collect_resources_path.py b/openpype/plugins/publish/collect_resources_path.py index 0f29fec054..9298ffe10c 100644 --- a/openpype/plugins/publish/collect_resources_path.py +++ b/openpype/plugins/publish/collect_resources_path.py @@ -68,7 +68,6 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): ] def process(self, instance): - anatomy = instance.context.data["anatomy"] template_data = copy.deepcopy(instance.data["anatomyData"]) @@ -86,6 +85,18 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): "hierarchy": instance.data["hierarchy"] }) + # Add fill keys for editorial publishing creating new entity + # TODO handle in editorial plugin + if ( + instance.data.get("newAssetPublishing") + and "asset" not in template_data + ): + asset_name = instance.data["asset"].split("/")[-1] + template_data["asset"] = asset_name + template_data["folder"] = { + "name": asset_name + } + publish_templates = anatomy.templates_obj["publish"] if "folder" in publish_templates: publish_folder = publish_templates["folder"].format_strict( From 476921ce7ad3207e414a129c20de55fb22cd7006 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 12 Dec 2023 13:55:41 +0100 Subject: [PATCH 24/24] move hierarchy key fill under 'newAssetPublishing' condition --- .../plugins/publish/collect_resources_path.py | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/openpype/plugins/publish/collect_resources_path.py b/openpype/plugins/publish/collect_resources_path.py index 9298ffe10c..af0ef17789 100644 --- a/openpype/plugins/publish/collect_resources_path.py +++ b/openpype/plugins/publish/collect_resources_path.py @@ -79,23 +79,18 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): "representation": "TEMP" }) - # For the first time publish - if instance.data.get("hierarchy"): - template_data.update({ - "hierarchy": instance.data["hierarchy"] - }) - # Add fill keys for editorial publishing creating new entity # TODO handle in editorial plugin - if ( - instance.data.get("newAssetPublishing") - and "asset" not in template_data - ): - asset_name = instance.data["asset"].split("/")[-1] - template_data["asset"] = asset_name - template_data["folder"] = { - "name": asset_name - } + if instance.data.get("newAssetPublishing"): + if "hierarchy" not in instance.data: + template_data["hierarchy"] = instance.data["hierarchy"] + + if "asset" not in template_data: + asset_name = instance.data["asset"].split("/")[-1] + template_data["asset"] = asset_name + template_data["folder"] = { + "name": asset_name + } publish_templates = anatomy.templates_obj["publish"] if "folder" in publish_templates: