From 12417e1ffa6edf8ca4b49f7b746eec165f58fc72 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Nov 2023 22:55:44 +0800 Subject: [PATCH 01/22] 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 02/22] 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 7c104e1336984071cbd341e4e4938421c094b54e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 6 Dec 2023 22:28:35 +0800 Subject: [PATCH 03/22] 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 04/22] 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 05/22] 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 06/22] 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 07/22] 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 08/22] 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 09/22] 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 b48253739af15cdb0a3e9610bacd9cacf16d871c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 7 Dec 2023 23:33:56 +0800 Subject: [PATCH 10/22] add the AYON/OP settings to enable extractor for model family in 3dsmax --- .../defaults/project_settings/max.json | 15 ++++ .../schemas/schema_max_publish.json | 75 +++++++++++++++++++ .../max/server/settings/publishers.py | 29 +++++++ server_addon/max/server/version.py | 2 +- 4 files changed, 120 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index 97fcf69e31..359db19226 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -56,6 +56,21 @@ "enabled": false, "optional": true, "family_plugins_mapping": [] + }, + "ExtractModelObj": { + "enabled": false, + "optional": true, + "active": true + }, + "ExtractModelFbx": { + "enabled": false, + "optional": true, + "active": true + }, + "ExtractModelUSD": { + "enabled": false, + "optional": true, + "active": true } } } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json index c6d37ae993..9077cf0c58 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json @@ -90,6 +90,81 @@ } } ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ExtractModelObj", + "label": "Extract Obj", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ExtractModelFbx", + "label": "Extract FBX", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ExtractModelUSD", + "label": "Extract Geometry (USD)", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] } ] } diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index b48f14a064..04a4bcb875 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -68,6 +68,20 @@ class PublishersModel(BaseSettingsModel): default_factory=ValidateLoadedPluginModel, title="Validate Loaded Plugin" ) + ExtractModelObj: BasicValidateModel = Field( + default_factory=BasicValidateModel, + title="Extract OBJ", + section="Publishers" + ) + ExtractModelFbx: BasicValidateModel = Field( + default_factory=BasicValidateModel, + title="Extract FBX" + ) + ExtractModelUSD: BasicValidateModel = Field( + default_factory=BasicValidateModel, + title="Extract Geometry (USD)" + ) + DEFAULT_PUBLISH_SETTINGS = { "ValidateFrameRange": { @@ -83,5 +97,20 @@ DEFAULT_PUBLISH_SETTINGS = { "enabled": False, "optional": True, "family_plugins_mapping": [] + }, + "ExtractModelObj": { + "enabled": False, + "optional": True, + "active": True + }, + "ExtractModelFbx": { + "enabled": False, + "optional": True, + "active": True + }, + "ExtractModelUSD": { + "enabled": False, + "optional": True, + "active": True } } diff --git a/server_addon/max/server/version.py b/server_addon/max/server/version.py index b3f4756216..ae7362549b 100644 --- a/server_addon/max/server/version.py +++ b/server_addon/max/server/version.py @@ -1 +1 @@ -__version__ = "0.1.2" +__version__ = "0.1.3" From bb5d48eae1b207cdff19c774636ddc13fdcf5f25 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 7 Dec 2023 16:48:43 +0100 Subject: [PATCH 11/22] Refactor code to skip instance creation for new assets - Removed the check for `newAssetPublishing` in `CollectResourcesPath.process()` - This change allows instances to be processed even if they are creating new assets --- openpype/plugins/publish/collect_resources_path.py | 5 ----- openpype/plugins/publish/extract_otio_audio_tracks.py | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/openpype/plugins/publish/collect_resources_path.py b/openpype/plugins/publish/collect_resources_path.py index a7f12bdfdb..0f29fec054 100644 --- a/openpype/plugins/publish/collect_resources_path.py +++ b/openpype/plugins/publish/collect_resources_path.py @@ -68,11 +68,6 @@ class CollectResourcesPath(pyblish.api.InstancePlugin): ] def process(self, instance): - # editorial would fail since they might not be in database yet - new_asset_publishing = instance.data.get("newAssetPublishing") - if new_asset_publishing: - self.log.debug("Instance is creating new asset. Skipping.") - return anatomy = instance.context.data["anatomy"] diff --git a/openpype/plugins/publish/extract_otio_audio_tracks.py b/openpype/plugins/publish/extract_otio_audio_tracks.py index 4b73321f02..d5ab1d6032 100644 --- a/openpype/plugins/publish/extract_otio_audio_tracks.py +++ b/openpype/plugins/publish/extract_otio_audio_tracks.py @@ -319,6 +319,7 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): Returns: str: temp fpath """ + name = name.replace("/", "_") return os.path.normpath( tempfile.mktemp( prefix="pyblish_tmp_{}_".format(name), From d9b18cc0f92a1b37a2fbe512bd775b2d120aa2ab Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 8 Dec 2023 00:47:09 +0800 Subject: [PATCH 12/22] add extract model and extract max scene --- .../defaults/project_settings/max.json | 10 ++++ .../schemas/schema_max_publish.json | 50 +++++++++++++++++++ .../max/server/settings/publishers.py | 18 +++++++ 3 files changed, 78 insertions(+) diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index 359db19226..ace7b7bdc2 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -71,6 +71,16 @@ "enabled": false, "optional": true, "active": true + }, + "ExtractModel": { + "enabled": true, + "optional": true, + "active": true + }, + "ExtractMaxSceneRaw": { + "enabled": true, + "optional": true, + "active": true } } } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json index 9077cf0c58..b4d85bda98 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json @@ -165,6 +165,56 @@ "label": "Active" } ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ExtractModel", + "label": "Extract Geometry (Alembic)", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ExtractMaxSceneRaw", + "label": "Extract Max Scene (Raw)", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + } + ] } ] } diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index 04a4bcb875..3977eaf075 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -81,6 +81,14 @@ class PublishersModel(BaseSettingsModel): default_factory=BasicValidateModel, title="Extract Geometry (USD)" ) + ExtractModel: BasicValidateModel = Field( + default_factory=BasicValidateModel, + title="Extract Geometry (Alembic)" + ) + ExtractMaxSceneRaw: BasicValidateModel = Field( + default_factory=BasicValidateModel, + title="Extract Max Scene (Raw)" + ) DEFAULT_PUBLISH_SETTINGS = { @@ -112,5 +120,15 @@ DEFAULT_PUBLISH_SETTINGS = { "enabled": False, "optional": True, "active": True + }, + "ExtractModel": { + "enabled": False, + "optional": True, + "active": True + }, + "ExtractMaxSceneRaw": { + "enabled": True, + "optional": True, + "active": True } } From b57d585d9f6e65dc500fbf183bacf8dcb748b22f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 8 Dec 2023 00:47:41 +0800 Subject: [PATCH 13/22] add extract alembic and extract max raw scene --- server_addon/max/server/settings/publishers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index 3977eaf075..4674ab25e7 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -71,7 +71,7 @@ class PublishersModel(BaseSettingsModel): ExtractModelObj: BasicValidateModel = Field( default_factory=BasicValidateModel, title="Extract OBJ", - section="Publishers" + section="Extractors" ) ExtractModelFbx: BasicValidateModel = Field( default_factory=BasicValidateModel, From 58001ee12e2ecc33ce7333f9c6ee114aeb59b450 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 8 Dec 2023 01:40:59 +0800 Subject: [PATCH 14/22] make sure some extractor not active while some active and all enabled --- .../settings/defaults/project_settings/max.json | 12 ++++++------ server_addon/max/server/settings/publishers.py | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index ace7b7bdc2..19c9d10496 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -58,19 +58,19 @@ "family_plugins_mapping": [] }, "ExtractModelObj": { - "enabled": false, + "enabled": true, "optional": true, - "active": true + "active": false }, "ExtractModelFbx": { - "enabled": false, + "enabled": true, "optional": true, - "active": true + "active": false }, "ExtractModelUSD": { - "enabled": false, + "enabled": true, "optional": true, - "active": true + "active": false }, "ExtractModel": { "enabled": true, diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index 4674ab25e7..d40d85a99b 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -107,22 +107,22 @@ DEFAULT_PUBLISH_SETTINGS = { "family_plugins_mapping": [] }, "ExtractModelObj": { - "enabled": False, + "enabled": True, "optional": True, - "active": True + "active": False }, "ExtractModelFbx": { - "enabled": False, + "enabled": True, "optional": True, - "active": True + "active": False }, "ExtractModelUSD": { - "enabled": False, + "enabled": True, "optional": True, - "active": True + "active": False }, "ExtractModel": { - "enabled": False, + "enabled": True, "optional": True, "active": True }, From c4570200ff7add65a9d06cebd94247c93c3af4ff Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 7 Dec 2023 22:08:19 +0100 Subject: [PATCH 15/22] Refactor code to handle missing "representations" key in instance data The code change modifies the `ExtractThumbnail` class in `extract_thumbnail.py`. It updates the loop that iterates over representations to handle cases where the "representations" key is missing from the instance data. This change ensures that cleanup occurs for representations with both "delete" and "need_thumbnail" tags. --- openpype/plugins/publish/extract_thumbnail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index 2b4a61845d..2b4ea0529a 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -56,7 +56,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # Make sure cleanup happens to representations which are having both # tags `delete` and `need_thumbnail` - for repre in tuple(instance.data["representations"]): + for repre in tuple(instance.data.get("representations", [])): tags = repre.get("tags") or [] # skip representations which are going to be published on farm if "publish_on_farm" in tags: From b855c72557f64f126b95ef5d38408a250eace688 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 8 Dec 2023 17:39:28 +0100 Subject: [PATCH 16/22] Refactor clip name extraction in create_editorial.py The code change updates the way the clip name is extracted from the OTIO file. The ".lower()" method has been removed to preserve case sensitivity. --- openpype/hosts/traypublisher/plugins/create/create_editorial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/traypublisher/plugins/create/create_editorial.py b/openpype/hosts/traypublisher/plugins/create/create_editorial.py index 26cce35d55..dce4a051fd 100644 --- a/openpype/hosts/traypublisher/plugins/create/create_editorial.py +++ b/openpype/hosts/traypublisher/plugins/create/create_editorial.py @@ -663,7 +663,7 @@ or updating already created. Publishing will create OTIO file. variant_name = instance_data["variant"] # basic unique asset name - clip_name = os.path.splitext(otio_clip.name)[0].lower() + clip_name = os.path.splitext(otio_clip.name)[0] project_doc = get_project(self.project_name) shot_name, shot_metadata = self._shot_metadata_solver.generate_data( From 41bdcf305e30155adb55f77dd6fde74e7ae37da2 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 9 Dec 2023 03:25:59 +0000 Subject: [PATCH 17/22] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 48688d5651..cdaafa0559 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.17.7-nightly.6" +__version__ = "3.17.7-nightly.7" From 8a1a1c3b15790859985c1120764b8a1dd32e91c3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 9 Dec 2023 03:26:34 +0000 Subject: [PATCH 18/22] 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 6d36857fe8026f793d30cabc15bb5e1d432e3570 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 11 Dec 2023 11:19:43 +0000 Subject: [PATCH 19/22] 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 20/22] 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 c1cba8640fb7da4222acde29b8261c77e71aa65b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 11 Dec 2023 15:52:12 +0100 Subject: [PATCH 21/22] 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/22] 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",