From 6ee7780972d2c37ccbf0279e5b7c21471afdba97 Mon Sep 17 00:00:00 2001 From: skacmazbelhaine Date: Tue, 6 Jun 2023 15:51:20 +0200 Subject: [PATCH 001/103] Update local settings --- website/docs/admin_settings_local.md | 27 +++++++++++++++++- .../assets/settings/settings_local_02.png | Bin 0 -> 11181 bytes 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 website/docs/assets/settings/settings_local_02.png diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index b254beb53b..214615f442 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -11,18 +11,43 @@ OpenPype stores some of it's settings and configuration in local file system. Th **Local Settings** GUI can be started from the tray menu. -![Local Settings](assets/settings/settings_local.png) +![Local Settings](assets/settings/settings_local_02.png) ## Categories + + ### OpenPype Mongo URL +The **Mongo URL** is the database URL given by your Studio. More details [here](https://openpype.io/docs/artist_getting_started#mongodb). + +
### General +**OpenPype Username** : enter your username (it can also take by default the computer session username). It signs your actions on **OpenPype**. + +
+ +**Admin permissions** : on checked, no need to enter a password (if defined) to access to the **Admin** section. + +
### Experimental tools +Futur version of existing tools or new ones. + +
+ +### Environments +**Environments** data of each software and there extra in-house needed to be loaded correctly. More details [here](https://openpype.io/docs/pype2/admin_config/#environments). + +
### Applications +Location of the softwares and there versions. More details [here](https://openpype.io/docs/admin_settings_system/#applications). + +
### Project Settings +The **Project Settings** allows to determine the root folder. More details [here](https://openpype.io/docs/module_site_sync/#project-settings). + diff --git a/website/docs/assets/settings/settings_local_02.png b/website/docs/assets/settings/settings_local_02.png new file mode 100644 index 0000000000000000000000000000000000000000..725c3327472cae5dc6271586aa4a1de2495104ca GIT binary patch literal 11181 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 T+AsLMj#fcN6 Date: Tue, 6 Jun 2023 15:51:32 +0200 Subject: [PATCH 002/103] Update local settings --- website/docs/admin_settings_local.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index 214615f442..222ee41515 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -36,7 +36,7 @@ Futur version of existing tools or new ones.
-### Environments +### Environments **Environments** data of each software and there extra in-house needed to be loaded correctly. More details [here](https://openpype.io/docs/pype2/admin_config/#environments).
@@ -48,6 +48,3 @@ Location of the softwares and there versions. More details [here](https://openpy ### Project Settings The **Project Settings** allows to determine the root folder. More details [here](https://openpype.io/docs/module_site_sync/#project-settings). - - - From ead57a2cafe2d451e99189d7d1aa94678a032033 Mon Sep 17 00:00:00 2001 From: skacmazbelhaine Date: Tue, 6 Jun 2023 16:30:11 +0200 Subject: [PATCH 003/103] Update local settings --- website/docs/admin_settings_local.md | 2 +- .../docs/assets/settings/settings_local.png | Bin 7212 -> 11181 bytes .../assets/settings/settings_local_02.png | Bin 11181 -> 0 bytes 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 website/docs/assets/settings/settings_local_02.png diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index 222ee41515..177c32451b 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -11,7 +11,7 @@ OpenPype stores some of it's settings and configuration in local file system. Th **Local Settings** GUI can be started from the tray menu. -![Local Settings](assets/settings/settings_local_02.png) +![Local Settings](assets/settings/settings_local.png) ## Categories diff --git a/website/docs/assets/settings/settings_local.png b/website/docs/assets/settings/settings_local.png index d2cf1c920d07e98bb53570f6b76ef039e642e741..725c3327472cae5dc6271586aa4a1de2495104ca 100644 GIT binary patch literal 11181 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 T+AsLMj#fcN6V{?TXm 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 Tu$%%u=7ApE)zK(Xvkdw#D_=3L diff --git a/website/docs/assets/settings/settings_local_02.png b/website/docs/assets/settings/settings_local_02.png deleted file mode 100644 index 725c3327472cae5dc6271586aa4a1de2495104ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11181 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 T+AsLMj#fcN6 Date: Wed, 7 Jun 2023 10:57:27 +0200 Subject: [PATCH 004/103] update after comments - local settings --- website/docs/admin_settings_local.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index 177c32451b..99e27731d0 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -18,7 +18,7 @@ OpenPype stores some of it's settings and configuration in local file system. Th ### OpenPype Mongo URL -The **Mongo URL** is the database URL given by your Studio. More details [here](https://openpype.io/docs/artist_getting_started#mongodb). +The **Mongo URL** is the database URL given by your Studio. More details [here](artist_getting_started#mongodb).
@@ -37,14 +37,14 @@ Futur version of existing tools or new ones.
### Environments -**Environments** data of each software and there extra in-house needed to be loaded correctly. More details [here](https://openpype.io/docs/pype2/admin_config/#environments). +Local replacement of the environment data of each software and additional internal data necessary to be loaded correctly.
### Applications -Location of the softwares and there versions. More details [here](https://openpype.io/docs/admin_settings_system/#applications). +Local override of software paths and their versions. More details [here](admin_settings_system/#applications).
### Project Settings -The **Project Settings** allows to determine the root folder. More details [here](https://openpype.io/docs/module_site_sync/#project-settings). +The **Project Settings** allows to determine the root folder. More details [here](module_site_sync/#local-settings). From 85af2013726edb61a76faff9122a28cd1f1749dc Mon Sep 17 00:00:00 2001 From: skacmazbelhaine Date: Thu, 8 Jun 2023 10:16:04 +0200 Subject: [PATCH 005/103] fix link path --- website/docs/admin_settings_local.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index 99e27731d0..33e0e374ce 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -18,7 +18,7 @@ OpenPype stores some of it's settings and configuration in local file system. Th ### OpenPype Mongo URL -The **Mongo URL** is the database URL given by your Studio. More details [here](artist_getting_started#mongodb). +The **Mongo URL** is the database URL given by your Studio. More details [here](artist_getting_started.md#mongodb).
@@ -42,9 +42,9 @@ Local replacement of the environment data of each software and additional intern
### Applications -Local override of software paths and their versions. More details [here](admin_settings_system/#applications). +Local override of software paths and their versions. More details [here](admin_settings_system.md#applications).
### Project Settings -The **Project Settings** allows to determine the root folder. More details [here](module_site_sync/#local-settings). +The **Project Settings** allows to determine the root folder. More details [here](module_site_sync.md#local-settings). From 54bdd152f6b3d67e240d487b264f1a674a75f876 Mon Sep 17 00:00:00 2001 From: skacmazbelhaine Date: Thu, 8 Jun 2023 11:03:19 +0200 Subject: [PATCH 006/103] Correction of line breaks --- website/docs/admin_settings_local.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index 33e0e374ce..142238f14f 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -15,36 +15,22 @@ OpenPype stores some of it's settings and configuration in local file system. Th ## Categories - - ### OpenPype Mongo URL The **Mongo URL** is the database URL given by your Studio. More details [here](artist_getting_started.md#mongodb). -
- ### General **OpenPype Username** : enter your username (it can also take by default the computer session username). It signs your actions on **OpenPype**. -
- **Admin permissions** : on checked, no need to enter a password (if defined) to access to the **Admin** section. -
- ### Experimental tools Futur version of existing tools or new ones. -
- ### Environments Local replacement of the environment data of each software and additional internal data necessary to be loaded correctly. -
- ### Applications Local override of software paths and their versions. More details [here](admin_settings_system.md#applications). -
- ### Project Settings The **Project Settings** allows to determine the root folder. More details [here](module_site_sync.md#local-settings). From aea1adab65ed3707a8963543313e0e6976082046 Mon Sep 17 00:00:00 2001 From: skacmazbelhaine Date: Tue, 13 Jun 2023 17:03:51 +0200 Subject: [PATCH 007/103] update local settings for global settings PR --- website/docs/admin_settings_local.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/website/docs/admin_settings_local.md b/website/docs/admin_settings_local.md index 142238f14f..8935b29fb5 100644 --- a/website/docs/admin_settings_local.md +++ b/website/docs/admin_settings_local.md @@ -19,18 +19,16 @@ OpenPype stores some of it's settings and configuration in local file system. Th The **Mongo URL** is the database URL given by your Studio. More details [here](artist_getting_started.md#mongodb). ### General -**OpenPype Username** : enter your username (it can also take by default the computer session username). It signs your actions on **OpenPype**. - -**Admin permissions** : on checked, no need to enter a password (if defined) to access to the **Admin** section. +**OpenPype Username** : enter your username (if not provided, it uses computer session username by default). This username is used to sign your actions on **OpenPype**, for example the "author" on a publish. +**Admin permissions** : When enabled you do not need to enter a password (if defined in Studio Settings) to access to the **Admin** section. ### Experimental tools -Futur version of existing tools or new ones. - +Future version of existing tools or new ones. ### Environments Local replacement of the environment data of each software and additional internal data necessary to be loaded correctly. ### Applications -Local override of software paths and their versions. More details [here](admin_settings_system.md#applications). +Local override of software executable paths for each version. More details [here](admin_settings_system.md#applications). ### Project Settings The **Project Settings** allows to determine the root folder. More details [here](module_site_sync.md#local-settings). From 8dea1724f9d13c1bb11f6840fb73228eb95b7086 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 23 Jun 2023 16:01:24 +0100 Subject: [PATCH 008/103] Check custom staging dir for Maya images folder. --- .../publish/validate_render_image_rule.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py b/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py index 78bb022785..96a57ee5d2 100644 --- a/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py +++ b/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py @@ -1,3 +1,5 @@ +import os + from maya import cmds import pyblish.api @@ -24,8 +26,12 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin): def process(self, instance): - required_images_rule = self.get_default_render_image_folder(instance) - current_images_rule = cmds.workspace(fileRuleEntry="images") + required_images_rule = os.path.normpath( + self.get_default_render_image_folder(self, instance) + ) + current_images_rule = os.path.normpath( + cmds.workspace(fileRuleEntry="images") + ) assert current_images_rule == required_images_rule, ( "Invalid workspace `images` file rule value: '{}'. " @@ -37,7 +43,9 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin): @classmethod def repair(cls, instance): - required_images_rule = cls.get_default_render_image_folder(instance) + required_images_rule = cls.get_default_render_image_folder( + cls, instance + ) current_images_rule = cmds.workspace(fileRuleEntry="images") if current_images_rule != required_images_rule: @@ -45,7 +53,16 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin): cmds.workspace(saveWorkspace=True) @staticmethod - def get_default_render_image_folder(instance): + def get_default_render_image_folder(cls, instance): + staging_dir = instance.data.get("stagingDir") + if staging_dir: + cls.log.debug( + "Staging dir found: \"{}\". Ignoring setting from " + "`project_settings/maya/RenderSettings/" + "default_render_image_folder`.".format(staging_dir) + ) + return staging_dir + return instance.context.data.get('project_settings')\ .get('maya') \ .get('RenderSettings') \ From 7dba2378844a2268ed1f8dc7f3cc6a8a3d47d02e Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 23 Jun 2023 16:21:45 +0100 Subject: [PATCH 009/103] Docs and setting note. --- .../schemas/schema_maya_render_settings.json | 2 +- .../project_settings/settings_project_global.md | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json index 636dfa114c..fc4e750e3b 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_render_settings.json @@ -12,7 +12,7 @@ { "type": "text", "key": "default_render_image_folder", - "label": "Default render image folder" + "label": "Default render image folder. This setting can be\noverwritten by custom staging directory profile;\n\"project_settings/global/tools/publish\n/custom_staging_dir_profiles\"." }, { "type": "boolean", diff --git a/website/docs/project_settings/settings_project_global.md b/website/docs/project_settings/settings_project_global.md index 5ddf247d98..e0481a8717 100644 --- a/website/docs/project_settings/settings_project_global.md +++ b/website/docs/project_settings/settings_project_global.md @@ -192,7 +192,7 @@ A profile may generate multiple outputs from a single input. Each output must de - Nuke extractor settings path: `project_settings/nuke/publish/ExtractReviewDataMov/outputs/baking/add_custom_tags` - Filtering by input length. Input may be video, sequence or single image. It is possible that `.mp4` should be created only when input is video or sequence and to create review `.png` when input is single frame. In some cases the output should be created even if it's single frame or multi frame input. - + ### Extract Burnin Plugin is responsible for adding burnins into review representations. @@ -226,13 +226,13 @@ A burnin profile may set multiple burnin outputs from one input. The burnin's na | **Bottom Centered** | Bottom center content. | str | "{username}" | | **Bottom Right** | Bottom right corner content. | str | "{frame_start}-{current_frame}-{frame_end}" | -Each burnin profile can be configured with additional family filtering and can -add additional tags to the burnin representation, these can be configured under +Each burnin profile can be configured with additional family filtering and can +add additional tags to the burnin representation, these can be configured under the profile's **Additional filtering** section. :::note Filename suffix -The filename suffix is appended to filename of the source representation. For -example, if the source representation has suffix **"h264"** and the burnin +The filename suffix is appended to filename of the source representation. For +example, if the source representation has suffix **"h264"** and the burnin suffix is **"client"** then the final suffix is **"h264_client"**. ::: @@ -343,6 +343,10 @@ One of the key advantages of this feature is that it allows users to choose the In some cases, these DCCs (Nuke, Houdini, Maya) automatically add a rendering path during the creation stage, which is then used in publishing. Creators and extractors of such DCCs need to use these profiles to fill paths in DCC's nodes to use this functionality. +:::note +Maya's setting `project_settings/maya/RenderSettings/default_render_image_folder` is be overwritten by the custom staging dir. +::: + The custom staging folder uses a path template configured in `project_anatomy/templates/others` with `transient` being a default example path that could be used. The template requires a 'folder' key for it to be usable as custom staging folder. ##### Known issues From 49dc54c64767c62c7c71718cf047a489886f84ab Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sun, 25 Jun 2023 15:37:52 +0100 Subject: [PATCH 010/103] Fix getting render paths. --- openpype/hosts/maya/plugins/publish/collect_render.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py index babd494758..ac318dfbf7 100644 --- a/openpype/hosts/maya/plugins/publish/collect_render.py +++ b/openpype/hosts/maya/plugins/publish/collect_render.py @@ -201,10 +201,10 @@ class CollectMayaRender(pyblish.api.ContextPlugin): # append full path aov_dict = {} - default_render_file = context.data.get('project_settings')\ - .get('maya')\ - .get('RenderSettings')\ - .get('default_render_image_folder') or "" + image_directory = os.path.join( + cmds.workspace(query=True, rootDirectory=True), + cmds.workspace(fileRuleEntry="images") + ) # replace relative paths with absolute. Render products are # returned as list of dictionaries. publish_meta_path = None @@ -212,8 +212,7 @@ class CollectMayaRender(pyblish.api.ContextPlugin): full_paths = [] aov_first_key = list(aov.keys())[0] for file in aov[aov_first_key]: - full_path = os.path.join(workspace, default_render_file, - file) + full_path = os.path.join(image_directory, file) full_path = full_path.replace("\\", "/") full_paths.append(full_path) publish_meta_path = os.path.dirname(full_path) From 96d796c4f5bdb51bd0461ad0f9a984019e48664c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sun, 25 Jun 2023 15:38:26 +0100 Subject: [PATCH 011/103] Account for custom staging directory persistentcy. --- .../hosts/maya/plugins/publish/extract_pointcache.py | 3 ++- .../hosts/maya/plugins/publish/extract_proxy_abc.py | 3 ++- .../hosts/maya/plugins/publish/extract_thumbnail.py | 3 ++- .../deadline/plugins/publish/submit_publish_job.py | 7 +++++-- openpype/plugins/publish/collect_rendered_files.py | 11 ++++++++--- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_pointcache.py b/openpype/hosts/maya/plugins/publish/extract_pointcache.py index f44c13767c..f0d914fd7a 100644 --- a/openpype/hosts/maya/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/maya/plugins/publish/extract_pointcache.py @@ -108,7 +108,8 @@ class ExtractAlembic(publish.Extractor): } instance.data["representations"].append(representation) - instance.context.data["cleanupFullPaths"].append(path) + if not instance.data.get("stagingDir_persistent", False): + instance.context.data["cleanupFullPaths"].append(path) self.log.info("Extracted {} to {}".format(instance, dirname)) diff --git a/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py b/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py index cf6351fdca..5894907795 100644 --- a/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py +++ b/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py @@ -80,7 +80,8 @@ class ExtractProxyAlembic(publish.Extractor): } instance.data["representations"].append(representation) - instance.context.data["cleanupFullPaths"].append(path) + if not instance.data.get("stagingDir_persistent", False): + instance.context.data["cleanupFullPaths"].append(path) self.log.info("Extracted {} to {}".format(instance, dirname)) # remove the bounding box diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 4160ac4cb2..3c7277121c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -92,7 +92,8 @@ class ExtractThumbnail(publish.Extractor): "Create temp directory {} for thumbnail".format(dst_staging) ) # Store new staging to cleanup paths - instance.context.data["cleanupFullPaths"].append(dst_staging) + if not instance.data.get("stagingDir_persistent", False): + instance.context.data["cleanupFullPaths"].append(dst_staging) filename = "{0}".format(instance.name) path = os.path.join(dst_staging, filename) diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index 69e9fb6449..7c29a68dc7 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -844,7 +844,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, do_not_add_review = False if data.get("review"): families.append("review") - elif data.get("review") == False: + elif data.get("review") is False: self.log.debug("Instance has review explicitly disabled.") do_not_add_review = True @@ -872,7 +872,10 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, "useSequenceForReview": data.get("useSequenceForReview", True), # map inputVersions `ObjectId` -> `str` so json supports it "inputVersions": list(map(str, data.get("inputVersions", []))), - "colorspace": instance.data.get("colorspace") + "colorspace": instance.data.get("colorspace"), + "stagingDir_persistent": instance.data.get( + "stagingDir_persistent", False + ) } # skip locking version if we are creating v01 diff --git a/openpype/plugins/publish/collect_rendered_files.py b/openpype/plugins/publish/collect_rendered_files.py index 6c8d1e9ca5..4b95d8ac44 100644 --- a/openpype/plugins/publish/collect_rendered_files.py +++ b/openpype/plugins/publish/collect_rendered_files.py @@ -124,6 +124,8 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): self.log.info( f"Adding audio to instance: {instance.data['audio']}") + return instance.data.get("stagingDir_persistent", False) + def process(self, context): self._context = context @@ -160,9 +162,12 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): legacy_io.Session.update(session_data) os.environ.update(session_data) session_is_set = True - self._process_path(data, anatomy) - context.data["cleanupFullPaths"].append(path) - context.data["cleanupEmptyDirs"].append(os.path.dirname(path)) + staging_dir_persistent = self._process_path(data, anatomy) + if not staging_dir_persistent: + context.data["cleanupFullPaths"].append(path) + context.data["cleanupEmptyDirs"].append( + os.path.dirname(path) + ) except Exception as e: self.log.error(e, exc_info=True) raise Exception("Error") from e From 1f6934afbfc18816c53e64d9484405c34ac6c97f Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 26 Jun 2023 16:38:29 +0100 Subject: [PATCH 012/103] staticmethod > classmethod --- .../hosts/maya/plugins/publish/validate_render_image_rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py b/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py index 96a57ee5d2..fdb069ae43 100644 --- a/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py +++ b/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py @@ -52,7 +52,7 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin): cmds.workspace(fileRule=("images", required_images_rule)) cmds.workspace(saveWorkspace=True) - @staticmethod + @classmethod def get_default_render_image_folder(cls, instance): staging_dir = instance.data.get("stagingDir") if staging_dir: From 8492491f8382acc9372017f8ae316117e11cb6ca Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 27 Jun 2023 10:40:51 +0100 Subject: [PATCH 013/103] Fix get_default_render_image_folder arguments. --- .../maya/plugins/publish/validate_render_image_rule.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py b/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py index fdb069ae43..f8c848e08b 100644 --- a/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py +++ b/openpype/hosts/maya/plugins/publish/validate_render_image_rule.py @@ -27,7 +27,7 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin): def process(self, instance): required_images_rule = os.path.normpath( - self.get_default_render_image_folder(self, instance) + self.get_default_render_image_folder(instance) ) current_images_rule = os.path.normpath( cmds.workspace(fileRuleEntry="images") @@ -43,9 +43,7 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin): @classmethod def repair(cls, instance): - required_images_rule = cls.get_default_render_image_folder( - cls, instance - ) + required_images_rule = cls.get_default_render_image_folder(instance) current_images_rule = cmds.workspace(fileRuleEntry="images") if current_images_rule != required_images_rule: From a6727800a36be1d8abb25f4ffe19858f552c0d94 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 3 Jul 2023 12:10:39 +0100 Subject: [PATCH 014/103] Dont change thumbnail extraction --- openpype/hosts/maya/plugins/publish/extract_thumbnail.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 3c7277121c..a4e5d4f8df 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -92,8 +92,6 @@ class ExtractThumbnail(publish.Extractor): "Create temp directory {} for thumbnail".format(dst_staging) ) # Store new staging to cleanup paths - if not instance.data.get("stagingDir_persistent", False): - instance.context.data["cleanupFullPaths"].append(dst_staging) filename = "{0}".format(instance.name) path = os.path.join(dst_staging, filename) From 5c44f12b37374b48c8f905834ff55e1bec99dee4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 00:51:48 +0200 Subject: [PATCH 015/103] Cleanup code - Refactor `get_file_node_files` because popping from `paths` by index should have been done in reversed order anyway. It's now changed to not need popping at all. - Removed unused `RENDERER_NODE_TYPES` and if-branch which collected `node_attrs` list which was unused + collected members which was also done outside of the if branch and thus generated no extra data. - Collected all materials from look set attributes at once instead of multiple queries - Collected all file nodes in history from a single query instead of per type - Restructured assignment of `instance.data["resources"]` to be more readable - Cached `PXR_NODES` only ones (Note: plugin load is checked on discovery of the collect look plugin) instead of querying plugin load and its nodes per file node per attribute - Removed some debug logs or combined some messages --- .../maya/plugins/publish/collect_look.py | 192 ++++++------------ 1 file changed, 64 insertions(+), 128 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index 287ddc228b..6832411190 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -17,11 +17,6 @@ SHAPE_ATTRS = ["castsShadows", "visibleInRefractions", "doubleSided", "opposite"] - -RENDERER_NODE_TYPES = [ - # redshift - "RedshiftMeshParameters" -] SHAPE_ATTRS = set(SHAPE_ATTRS) @@ -36,12 +31,13 @@ def get_pxr_multitexture_file_attrs(node): FILE_NODES = { + # maya "file": "fileTextureName", - + # arnold (mtoa) "aiImage": "filename", - + # redshift "RedshiftNormalMap": "tex0", - + # renderman "PxrBump": "filename", "PxrNormalMap": "filename", "PxrMultiTexture": get_pxr_multitexture_file_attrs, @@ -49,6 +45,15 @@ FILE_NODES = { "PxrTexture": "filename" } +# Cache pixar dependency node types so we can perform a type lookup against it +PXR_NODES = set() +if cmds.pluginInfo("RenderMan_for_Maya", query=True, loaded=True): + PXR_NODES = set( + cmds.pluginInfo("RenderMan_for_Maya", + query=True, + dependNode=True) + ) + def get_attributes(dictionary, attr, node=None): # type: (dict, str, str) -> list @@ -232,20 +237,17 @@ def get_file_node_files(node): """ paths = get_file_node_paths(node) - sequences = [] - replaces = [] + + # For sequences get all files and filter to only existing files + result = [] for index, path in enumerate(paths): if node_uses_image_sequence(node, path): glob_pattern = seq_to_glob(path) - sequences.extend(glob.glob(glob_pattern)) - replaces.append(index) + result.extend(glob.glob(glob_pattern)) + elif os.path.exists(path): + result.append(path) - for index in replaces: - paths.pop(index) - - paths.extend(sequences) - - return [p for p in paths if os.path.exists(p)] + return result class CollectLook(pyblish.api.InstancePlugin): @@ -260,7 +262,7 @@ class CollectLook(pyblish.api.InstancePlugin): membership relations. Collects: - lookAttribtutes (list): Nodes in instance with their altered attributes + lookAttributes (list): Nodes in instance with their altered attributes lookSetRelations (list): Sets and their memberships lookSets (list): List of set names included in the look @@ -285,76 +287,31 @@ class CollectLook(pyblish.api.InstancePlugin): instance: Instance to collect. """ - self.log.info("Looking for look associations " - "for %s" % instance.data['name']) - - # Discover related object sets - self.log.info("Gathering sets ...") - sets = self.collect_sets(instance) + self.log.debug("Looking for look associations " + "for %s" % instance.data['name']) # Lookup set (optimization) instance_lookup = set(cmds.ls(instance, long=True)) - self.log.info("Gathering set relations ...") - # Ensure iteration happen in a list so we can remove keys from the + # Discover related object sets + self.log.debug("Gathering sets ...") + sets = self.collect_sets(instance) + + # Ensure iteration happen in a list to allow removing keys from the # dict within the loop - - # skipped types of attribute on render specific nodes - disabled_types = ["message", "TdataCompound"] - + self.log.info("Gathering set relations ...") for obj_set in list(sets): self.log.debug("From {}".format(obj_set)) - - # if node is specified as renderer node type, it will be - # serialized with its attributes. - if cmds.nodeType(obj_set) in RENDERER_NODE_TYPES: - self.log.info("- {} is {}".format( - obj_set, cmds.nodeType(obj_set))) - - node_attrs = [] - - # serialize its attributes so they can be recreated on look - # load. - for attr in cmds.listAttr(obj_set): - # skip publishedNodeInfo attributes as they break - # getAttr() and we don't need them anyway - if attr.startswith("publishedNodeInfo"): - continue - - # skip attributes types defined in 'disabled_type' list - if cmds.getAttr("{}.{}".format(obj_set, attr), type=True) in disabled_types: # noqa - continue - - node_attrs.append(( - attr, - cmds.getAttr("{}.{}".format(obj_set, attr)), - cmds.getAttr( - "{}.{}".format(obj_set, attr), type=True) - )) - - for member in cmds.ls( - cmds.sets(obj_set, query=True), long=True): - member_data = self.collect_member_data(member, - instance_lookup) - if not member_data: - continue - - # Add information of the node to the members list - sets[obj_set]["members"].append(member_data) - # Get all nodes of the current objectSet (shadingEngine) for member in cmds.ls(cmds.sets(obj_set, query=True), long=True): member_data = self.collect_member_data(member, instance_lookup) - if not member_data: - continue - - # Add information of the node to the members list - sets[obj_set]["members"].append(member_data) + if member_data: + # Add information of the node to the members list + sets[obj_set]["members"].append(member_data) # Remove sets that didn't have any members assigned in the end # Thus the data will be limited to only what we need. - self.log.info("obj_set {}".format(sets[obj_set])) if not sets[obj_set]["members"]: self.log.info( "Removing redundant set information: {}".format(obj_set)) @@ -382,35 +339,26 @@ class CollectLook(pyblish.api.InstancePlugin): "rman__displacement" ] if look_sets: - materials = [] + self.log.debug("Found look sets:\n{}".format(look_sets)) + # Get all material attrs for all look sets to retrieve their inputs + existing_attrs = [] for look in look_sets: - for at in shader_attrs: - try: - con = cmds.listConnections("{}.{}".format(look, at)) - except ValueError: - # skip attributes that are invalid in current - # context. For example in the case where - # Arnold is not enabled. - continue - if con: - materials.extend(con) + for attr in shader_attrs: + if cmds.attributeQuery(attr, node=look_sets, exists=True): + existing_attrs.append("{}.{}".format(look, attr)) + materials = cmds.listConnections(existing_attrs, + source=True, + destination=False) or [] + self.log.debug("Found materials:\n{}".format(materials)) - self.log.info("Found materials:\n{}".format(materials)) - - self.log.info("Found the following sets:\n{}".format(look_sets)) # Get the entire node chain of the look sets - # history = cmds.listHistory(look_sets) - history = [] - for material in materials: - history.extend(cmds.listHistory(material, ac=True)) - - # handle VrayPluginNodeMtl node - see #1397 - vray_plugin_nodes = cmds.ls( - history, type="VRayPluginNodeMtl", long=True) - for vray_node in vray_plugin_nodes: - history.extend(cmds.listHistory(vray_node, ac=True)) + # history = cmds.listHistory(look_sets, allConnections=True) + history = cmds.listHistory(materials, allConnections=True) + # Since we retrieved history only of the connected materials + # connected to the look sets above we now add direct history + # for some of the look sets directly # handling render attribute sets render_set_types = [ "VRayDisplacement", @@ -428,20 +376,17 @@ class CollectLook(pyblish.api.InstancePlugin): or [] ) - all_supported_nodes = FILE_NODES.keys() - files = [] - for node_type in all_supported_nodes: - files.extend(cmds.ls(history, type=node_type, long=True)) + files = cmds.ls(history, + type=list(FILE_NODES.keys()), + long=True) - self.log.info("Collected file nodes:\n{}".format(files)) + self.log.info("Collected file nodes:{}".format(files)) # Collect textures if any file nodes are found - instance.data["resources"] = [] - for n in files: - for res in self.collect_resources(n): - instance.data["resources"].append(res) - - self.log.info("Collected resources: {}".format( - instance.data["resources"])) + resources = [] + for node in files: + resources.extend(self.collect_resources(node)) + instance.data["resources"] = resources + self.log.debug("Collected resources: {}".format(resources)) # Log warning when no relevant sets were retrieved for the look. if ( @@ -456,7 +401,7 @@ class CollectLook(pyblish.api.InstancePlugin): instance.extend(shader for shader in look_sets if shader not in instance_lookup) - self.log.info("Collected look for %s" % instance) + self.log.debug("Collected look for %s" % instance) def collect_sets(self, instance): """Collect all objectSets which are of importance for publishing @@ -536,14 +481,14 @@ class CollectLook(pyblish.api.InstancePlugin): # Collect changes to "custom" attributes node_attrs = get_look_attrs(node) - self.log.info( - "Node \"{0}\" attributes: {1}".format(node, node_attrs) - ) - # Only include if there are any properties we care about if not node_attrs: continue + self.log.debug( + "Node \"{0}\" attributes: {1}".format(node, node_attrs) + ) + node_attributes = {} for attr in node_attrs: if not cmds.attributeQuery(attr, node=node, exists=True): @@ -574,14 +519,12 @@ class CollectLook(pyblish.api.InstancePlugin): Returns: dict """ - self.log.debug("processing: {}".format(node)) - all_supported_nodes = FILE_NODES.keys() - if cmds.nodeType(node) not in all_supported_nodes: + if cmds.nodeType(node) not in FILE_NODES: self.log.error( "Unsupported file node: {}".format(cmds.nodeType(node))) raise AssertionError("Unsupported file node") - self.log.debug(" - got {}".format(cmds.nodeType(node))) + self.log.debug("processing: {} ({})".format(node, cmds.nodeType(node))) attributes = get_attributes(FILE_NODES, cmds.nodeType(node), node) for attribute in attributes: @@ -613,14 +556,7 @@ class CollectLook(pyblish.api.InstancePlugin): # renderman allows nodes to have filename attribute empty while # you can have another incoming connection from different node. - pxr_nodes = set() - if cmds.pluginInfo("RenderMan_for_Maya", query=True, loaded=True): - pxr_nodes = set( - cmds.pluginInfo("RenderMan_for_Maya", - query=True, - dependNode=True) - ) - if not source and cmds.nodeType(node) in pxr_nodes: + if not source and cmds.nodeType(node) in PXR_NODES: self.log.info("Renderman: source is empty, skipping...") continue # We replace backslashes with forward slashes because V-Ray From fab6c0d9c603e1edfcdd86cc007cd7d0776a7ef5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 01:24:00 +0200 Subject: [PATCH 016/103] Fix typo --- openpype/hosts/maya/plugins/publish/collect_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index 6832411190..e08bf88872 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -345,7 +345,7 @@ class CollectLook(pyblish.api.InstancePlugin): existing_attrs = [] for look in look_sets: for attr in shader_attrs: - if cmds.attributeQuery(attr, node=look_sets, exists=True): + if cmds.attributeQuery(attr, node=look, exists=True): existing_attrs.append("{}.{}".format(look, attr)) materials = cmds.listConnections(existing_attrs, source=True, From 40dc747f9ae1ba867e8afc14735c1e0d3a40ea0e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 01:24:33 +0200 Subject: [PATCH 017/103] Fix file nodes filtering --- openpype/hosts/maya/plugins/publish/collect_look.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index e08bf88872..21e3d83d13 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -45,6 +45,13 @@ FILE_NODES = { "PxrTexture": "filename" } +# Keep only node types that actually exist +all_node_types = set(cmds.allNodeTypes()) +for node_type in list(FILE_NODES.keys()): + if node_type not in all_node_types: + FILE_NODES.pop(node_type) +del all_node_types + # Cache pixar dependency node types so we can perform a type lookup against it PXR_NODES = set() if cmds.pluginInfo("RenderMan_for_Maya", query=True, loaded=True): @@ -377,10 +384,13 @@ class CollectLook(pyblish.api.InstancePlugin): ) files = cmds.ls(history, + # It's important only node types are passed that + # exist (e.g. for loaded plugins) because otherwise + # the result will turn back empty type=list(FILE_NODES.keys()), long=True) - self.log.info("Collected file nodes:{}".format(files)) + self.log.info("Collected file nodes: {}".format(files)) # Collect textures if any file nodes are found resources = [] for node in files: From 38ab207e06b63eec371e8ef1cf83c90b73d6630d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 01:30:09 +0200 Subject: [PATCH 018/103] Cosmetics: remove new line in log --- openpype/hosts/maya/plugins/publish/collect_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index 21e3d83d13..0104c4e1dd 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -357,7 +357,7 @@ class CollectLook(pyblish.api.InstancePlugin): materials = cmds.listConnections(existing_attrs, source=True, destination=False) or [] - self.log.debug("Found materials:\n{}".format(materials)) + self.log.debug("Found materials: {}".format(materials)) # Get the entire node chain of the look sets # history = cmds.listHistory(look_sets, allConnections=True) From ae3364a833efc39ce82d073a4402d95b2d78735d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 01:30:28 +0200 Subject: [PATCH 019/103] Cosmetics: remove new line in logs --- openpype/hosts/maya/plugins/publish/collect_look.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index 0104c4e1dd..f8c5ccf4ee 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -346,7 +346,7 @@ class CollectLook(pyblish.api.InstancePlugin): "rman__displacement" ] if look_sets: - self.log.debug("Found look sets:\n{}".format(look_sets)) + self.log.debug("Found look sets: {}".format(look_sets)) # Get all material attrs for all look sets to retrieve their inputs existing_attrs = [] From 58217d88c57700e7e645d5b7dbca2bc6e5f92bf3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 11:11:59 +0200 Subject: [PATCH 020/103] Ensure file nodes are processed only once --- openpype/hosts/maya/plugins/publish/collect_look.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index f8c5ccf4ee..80c4b61de5 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -383,6 +383,9 @@ class CollectLook(pyblish.api.InstancePlugin): or [] ) + # Ensure unique entries only + history = list(set(history)) + files = cmds.ls(history, # It's important only node types are passed that # exist (e.g. for loaded plugins) because otherwise @@ -390,10 +393,13 @@ class CollectLook(pyblish.api.InstancePlugin): type=list(FILE_NODES.keys()), long=True) + # Sort for log readability + files.sort() + self.log.info("Collected file nodes: {}".format(files)) # Collect textures if any file nodes are found resources = [] - for node in files: + for node in files: # sort for log readability resources.extend(self.collect_resources(node)) instance.data["resources"] = resources self.log.debug("Collected resources: {}".format(resources)) From 95e763dee4d592d94180cf9047eb9210fae9246c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 11:12:46 +0200 Subject: [PATCH 021/103] Clarify that computed source is only used for logging by moving logic closer together --- .../maya/plugins/publish/collect_look.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index 80c4b61de5..321df3e61c 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -548,27 +548,28 @@ class CollectLook(pyblish.api.InstancePlugin): node, attribute )) - computed_attribute = "{}.{}".format(node, attribute) - if attribute == "fileTextureName": - computed_attribute = node + ".computedFileTextureNamePattern" - self.log.info(" - file source: {}".format(source)) color_space_attr = "{}.colorSpace".format(node) try: color_space = cmds.getAttr(color_space_attr) except ValueError: # node doesn't have colorspace attribute color_space = "Raw" + # Compare with the computed file path, e.g. the one with # the pattern in it, to generate some logging information # about this difference - computed_source = cmds.getAttr(computed_attribute) - if source != computed_source: - self.log.debug("Detected computed file pattern difference " - "from original pattern: {0} " - "({1} -> {2})".format(node, - source, - computed_source)) + # Only for file nodes with `fileTextureName` attribute + if attribute == "fileTextureName": + computed_source = cmds.getAttr( + "{}.computedFileTextureNamePattern".format(node) + ) + if source != computed_source: + self.log.debug("Detected computed file pattern difference " + "from original pattern: {0} " + "({1} -> {2})".format(node, + source, + computed_source)) # renderman allows nodes to have filename attribute empty while # you can have another incoming connection from different node. From a54cddf0f378eb80bb4d2bd2c7386415ed69f034 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 6 Jul 2023 11:13:12 +0200 Subject: [PATCH 022/103] Clarify in log that it's processing a resource --- openpype/hosts/maya/plugins/publish/collect_look.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index 321df3e61c..bbe25c559e 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -540,7 +540,9 @@ class CollectLook(pyblish.api.InstancePlugin): "Unsupported file node: {}".format(cmds.nodeType(node))) raise AssertionError("Unsupported file node") - self.log.debug("processing: {} ({})".format(node, cmds.nodeType(node))) + self.log.debug( + "Collecting resource: {} ({})".format(node, cmds.nodeType(node)) + ) attributes = get_attributes(FILE_NODES, cmds.nodeType(node), node) for attribute in attributes: From f7c368892b6a34a808b21a0f4da51b9f74b3228f Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 13 Jul 2023 15:49:16 +0100 Subject: [PATCH 023/103] Fix Maya Deadline submit plugin --- .../deadline/plugins/publish/submit_maya_deadline.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 159ac43289..8193ca2734 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -289,7 +289,6 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, def process_submission(self): instance = self._instance - context = instance.context filepath = self.scene_path # publish if `use_publish` else workfile @@ -306,13 +305,11 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, self._patch_workfile() # Gather needed data ------------------------------------------------ - workspace = context.data["workspaceDir"] - default_render_file = instance.context.data.get('project_settings')\ - .get('maya')\ - .get('RenderSettings')\ - .get('default_render_image_folder') filename = os.path.basename(filepath) - dirname = os.path.join(workspace, default_render_file) + dirname = os.path.join( + cmds.workspace(query=True, rootDirectory=True), + cmds.workspace(fileRuleEntry="images") + ) # Fill in common data to payload ------------------------------------ # TODO: Replace these with collected data from CollectRender From 58d2bcad88ca7ccd69a04fa6ec1e85dd693ac462 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 8 Aug 2023 12:07:57 +0200 Subject: [PATCH 024/103] Extract active view as thumbnail --- .../publish/extract_active_view_thumbnail.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py diff --git a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py new file mode 100644 index 0000000000..1bf010896a --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py @@ -0,0 +1,51 @@ +import maya.api.OpenMaya as om +import maya.api.OpenMayaUI as omui + +import pyblish.api +import tempfile + + +class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): + """Set instance thumbnail to a screengrab of current active viewport. + + This makes it so that if an instance does not have a thumbnail set yet that + it will get a thumbnail of the currently active view at the time of + publishing as a fallback. + + """ + order = pyblish.api.ExtractorOrder + 0.49 + label = "Active View Thumbnail" + families = ["workfile"] + hosts = ["maya"] + + def process(self, instance): + thumbnail = instance.data.get("thumbnailPath") + if not thumbnail: + view_thumbnail = self.get_view_thumbnail(instance) + if not view_thumbnail: + return + + self.log.debug("Setting instance thumbnail path to: {}".format( + view_thumbnail + )) + instance.data["thumbnailPath"] = view_thumbnail + + def get_view_thumbnail(self, instance): + cache_key = "__maya_view_thumbnail" + context = instance.context + + if cache_key not in context.data: + # Generate only a single thumbnail, even for multiple instances + with tempfile.NamedTemporaryFile(suffix="_thumbnail.jpg", + delete=False) as f: + path = f.name + + view = omui.M3dView.active3dView() + image = om.MImage() + view.readColorBuffer(image, True) + image.writeToFile(path, "jpg") + self.log.debug("Generated thumbnail: {}".format(path)) + + context.data[cache_key] = path + return context.data[cache_key] + From 4049d9acb148e93f11849bc2395b904c0ff13dcf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 8 Aug 2023 12:12:14 +0200 Subject: [PATCH 025/103] Cosmetics - good doggy! --- .../hosts/maya/plugins/publish/extract_active_view_thumbnail.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py index 1bf010896a..cb039cbf51 100644 --- a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py @@ -48,4 +48,3 @@ class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): context.data[cache_key] = path return context.data[cache_key] - From 7b74d0b91ddaf0d1d8bda72a84d9cea87ba2f122 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 9 Aug 2023 20:21:25 +0800 Subject: [PATCH 026/103] add ornatrix alembic loader --- openpype/hosts/max/plugins/load/load_model.py | 2 +- .../max/plugins/load/load_model_ornatrix.py | 74 +++++++++++++++++++ .../hosts/max/plugins/load/load_pointcache.py | 2 +- .../plugins/load/load_pointcache_ornatrix.py | 70 ++++++++++++++++++ 4 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 openpype/hosts/max/plugins/load/load_model_ornatrix.py create mode 100644 openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index cff82a593c..c149f939a2 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -9,7 +9,7 @@ class ModelAbcLoader(load.LoaderPlugin): """Loading model with the Alembic loader.""" families = ["model"] - label = "Load Model(Alembic)" + label = "Load Model(Alembic) with Max" representations = ["abc"] order = -10 icon = "code-fork" diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py new file mode 100644 index 0000000000..d92e92f63b --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_model_ornatrix.py @@ -0,0 +1,74 @@ +import os +from openpype.pipeline import load, get_representation_path +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class ModelAbcLoader(load.LoaderPlugin): + """Loading model with the Ornatrix Alembic loader.""" + + families = ["model"] + label = "Load Model(Alembic) with Ornatrix" + representations = ["abc"] + order = -10 + icon = "code-fork" + color = "orange" + + def load(self, context, name=None, namespace=None, data=None): + from pymxs import runtime as rt + + file_path = os.path.normpath(self.filepath_from_context(context)) + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = True + rt.AlembicImport.CustomAttributes = True + rt.AlembicImport.UVs = True + rt.AlembicImport.VertexColors = True + rt.importFile(file_path) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + abc_container = rt.Container(name=name) + for abc in scene_object_after: + abc.Parent = abc_container + + return containerise( + name, [abc_container], context, loader=self.__class__.__name__ + ) + + def update(self, container, representation): + from pymxs import runtime as rt + + path = get_representation_path(representation) + node_name = container["instance_node"] + instance_name, _ = os.path.splitext(node_name) + container = rt.getNodeByName(instance_name) + for children in container.Children: + rt.Delete(children) + + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = True + rt.AlembicImport.CustomAttributes = True + rt.AlembicImport.UVs = True + rt.AlembicImport.VertexColors = True + rt.importFile(path) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + for scene_object in scene_object_after: + scene_object.Parent = container + + lib.imprint( + container["instance_node"], + {"representation": str(representation["_id"])}, + ) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + from pymxs import runtime as rt + + node = rt.GetNodeByName(container["instance_node"]) + rt.Delete(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 290503e053..e59ad09c9f 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -14,7 +14,7 @@ class AbcLoader(load.LoaderPlugin): """Alembic loader.""" families = ["camera", "animation", "pointcache"] - label = "Load Alembic" + label = "Load Alembic with Max" representations = ["abc"] order = -10 icon = "code-fork" diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py new file mode 100644 index 0000000000..0b0932da6a --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -0,0 +1,70 @@ +import os +from openpype.pipeline import load, get_representation_path +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class ModelAbcLoader(load.LoaderPlugin): + """Ornatrix Alembic loader.""" + + families = ["camera", "animation", "pointcache"] + label = "Load Model(Alembic) with Ornatrix" + representations = ["abc"] + order = -10 + icon = "code-fork" + color = "orange" + + def load(self, context, name=None, namespace=None, data=None): + from pymxs import runtime as rt + + file_path = os.path.normpath(self.filepath_from_context(context)) + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = True + rt.AlembicImport.CustomAttributes = True + rt.importFile(file_path) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + abc_container = rt.Container(name=name) + for abc in scene_object_after: + abc.Parent = abc_container + + return containerise( + name, [abc_container], context, loader=self.__class__.__name__ + ) + + def update(self, container, representation): + from pymxs import runtime as rt + + path = get_representation_path(representation) + node_name = container["instance_node"] + instance_name, _ = os.path.splitext(node_name) + container = rt.getNodeByName(instance_name) + for children in container.Children: + rt.Delete(children) + + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = False + rt.AlembicImport.CustomAttributes = True + rt.importFile(path) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + for scene_object in scene_object_after: + scene_object.Parent = container + + lib.imprint( + container["instance_node"], + {"representation": str(representation["_id"])}, + ) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + from pymxs import runtime as rt + + node = rt.GetNodeByName(container["instance_node"]) + rt.Delete(node) From 8a175b06edb6b6ca8039ac6560c19541d923bd0f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 9 Aug 2023 20:29:20 +0800 Subject: [PATCH 027/103] rename the label --- openpype/hosts/max/plugins/load/load_model.py | 2 +- openpype/hosts/max/plugins/load/load_model_ornatrix.py | 2 +- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index c149f939a2..2f402efef8 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -9,7 +9,7 @@ class ModelAbcLoader(load.LoaderPlugin): """Loading model with the Alembic loader.""" families = ["model"] - label = "Load Model(Alembic) with Max" + label = "Load Model with Alembic" representations = ["abc"] order = -10 icon = "code-fork" diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py index d92e92f63b..8dc34278f5 100644 --- a/openpype/hosts/max/plugins/load/load_model_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_model_ornatrix.py @@ -8,7 +8,7 @@ class ModelAbcLoader(load.LoaderPlugin): """Loading model with the Ornatrix Alembic loader.""" families = ["model"] - label = "Load Model(Alembic) with Ornatrix" + label = "Load Model with Ornatrix Alembic" representations = ["abc"] order = -10 icon = "code-fork" diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 0b0932da6a..663c64bc0a 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -8,7 +8,7 @@ class ModelAbcLoader(load.LoaderPlugin): """Ornatrix Alembic loader.""" families = ["camera", "animation", "pointcache"] - label = "Load Model(Alembic) with Ornatrix" + label = "Load Alembic with Ornatrix" representations = ["abc"] order = -10 icon = "code-fork" From 938185c20835b545fa5c3b4b3e7673264509acf5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 9 Aug 2023 20:32:39 +0800 Subject: [PATCH 028/103] rename the class name --- openpype/hosts/max/plugins/load/load_model_ornatrix.py | 2 +- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py index 8dc34278f5..424820e6e6 100644 --- a/openpype/hosts/max/plugins/load/load_model_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_model_ornatrix.py @@ -4,7 +4,7 @@ from openpype.hosts.max.api.pipeline import containerise from openpype.hosts.max.api import lib -class ModelAbcLoader(load.LoaderPlugin): +class ModelOxAbcLoader(load.LoaderPlugin): """Loading model with the Ornatrix Alembic loader.""" families = ["model"] diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 663c64bc0a..0d04dbdef3 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -4,7 +4,7 @@ from openpype.hosts.max.api.pipeline import containerise from openpype.hosts.max.api import lib -class ModelAbcLoader(load.LoaderPlugin): +class OxAbcLoader(load.LoaderPlugin): """Ornatrix Alembic loader.""" families = ["camera", "animation", "pointcache"] From cb48a2268c996ade66744540c2019b3eb8d06e98 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 10 Aug 2023 00:19:52 +0800 Subject: [PATCH 029/103] add the using alembic import back to the importfile --- openpype/hosts/max/plugins/load/load_model.py | 3 +- .../max/plugins/load/load_model_ornatrix.py | 74 ------------------- .../hosts/max/plugins/load/load_pointcache.py | 3 +- .../plugins/load/load_pointcache_ornatrix.py | 70 ------------------ 4 files changed, 4 insertions(+), 146 deletions(-) delete mode 100644 openpype/hosts/max/plugins/load/load_model_ornatrix.py delete mode 100644 openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index 2f402efef8..288fc58454 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -30,7 +30,8 @@ class ModelAbcLoader(load.LoaderPlugin): rt.AlembicImport.CustomAttributes = True rt.AlembicImport.UVs = True rt.AlembicImport.VertexColors = True - rt.importFile(file_path, rt.name("noPrompt")) + rt.importFile( + file_path, rt.name("noPrompt"), using=rt.AlembicImport) abc_after = { c diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py deleted file mode 100644 index 424820e6e6..0000000000 --- a/openpype/hosts/max/plugins/load/load_model_ornatrix.py +++ /dev/null @@ -1,74 +0,0 @@ -import os -from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise -from openpype.hosts.max.api import lib - - -class ModelOxAbcLoader(load.LoaderPlugin): - """Loading model with the Ornatrix Alembic loader.""" - - families = ["model"] - label = "Load Model with Ornatrix Alembic" - representations = ["abc"] - order = -10 - icon = "code-fork" - color = "orange" - - def load(self, context, name=None, namespace=None, data=None): - from pymxs import runtime as rt - - file_path = os.path.normpath(self.filepath_from_context(context)) - scene_object_before = [obj for obj in rt.rootNode.Children] - rt.AlembicImport.ImportToRoot = True - rt.AlembicImport.CustomAttributes = True - rt.AlembicImport.UVs = True - rt.AlembicImport.VertexColors = True - rt.importFile(file_path) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - - abc_container = rt.Container(name=name) - for abc in scene_object_after: - abc.Parent = abc_container - - return containerise( - name, [abc_container], context, loader=self.__class__.__name__ - ) - - def update(self, container, representation): - from pymxs import runtime as rt - - path = get_representation_path(representation) - node_name = container["instance_node"] - instance_name, _ = os.path.splitext(node_name) - container = rt.getNodeByName(instance_name) - for children in container.Children: - rt.Delete(children) - - scene_object_before = [obj for obj in rt.rootNode.Children] - rt.AlembicImport.ImportToRoot = True - rt.AlembicImport.CustomAttributes = True - rt.AlembicImport.UVs = True - rt.AlembicImport.VertexColors = True - rt.importFile(path) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - - for scene_object in scene_object_after: - scene_object.Parent = container - - lib.imprint( - container["instance_node"], - {"representation": str(representation["_id"])}, - ) - - def switch(self, container, representation): - self.update(container, representation) - - def remove(self, container): - from pymxs import runtime as rt - - node = rt.GetNodeByName(container["instance_node"]) - rt.Delete(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index e59ad09c9f..24bcf58582 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -33,7 +33,8 @@ class AbcLoader(load.LoaderPlugin): } rt.AlembicImport.ImportToRoot = False - rt.importFile(file_path, rt.name("noPrompt")) + rt.importFile( + file_path, rt.name("noPrompt"), using=rt.AlembicImport) abc_after = { c diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py deleted file mode 100644 index 0d04dbdef3..0000000000 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise -from openpype.hosts.max.api import lib - - -class OxAbcLoader(load.LoaderPlugin): - """Ornatrix Alembic loader.""" - - families = ["camera", "animation", "pointcache"] - label = "Load Alembic with Ornatrix" - representations = ["abc"] - order = -10 - icon = "code-fork" - color = "orange" - - def load(self, context, name=None, namespace=None, data=None): - from pymxs import runtime as rt - - file_path = os.path.normpath(self.filepath_from_context(context)) - scene_object_before = [obj for obj in rt.rootNode.Children] - rt.AlembicImport.ImportToRoot = True - rt.AlembicImport.CustomAttributes = True - rt.importFile(file_path) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - - abc_container = rt.Container(name=name) - for abc in scene_object_after: - abc.Parent = abc_container - - return containerise( - name, [abc_container], context, loader=self.__class__.__name__ - ) - - def update(self, container, representation): - from pymxs import runtime as rt - - path = get_representation_path(representation) - node_name = container["instance_node"] - instance_name, _ = os.path.splitext(node_name) - container = rt.getNodeByName(instance_name) - for children in container.Children: - rt.Delete(children) - - scene_object_before = [obj for obj in rt.rootNode.Children] - rt.AlembicImport.ImportToRoot = False - rt.AlembicImport.CustomAttributes = True - rt.importFile(path) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - - for scene_object in scene_object_after: - scene_object.Parent = container - - lib.imprint( - container["instance_node"], - {"representation": str(representation["_id"])}, - ) - - def switch(self, container, representation): - self.update(container, representation) - - def remove(self, container): - from pymxs import runtime as rt - - node = rt.GetNodeByName(container["instance_node"]) - rt.Delete(node) From 5cb43a141476fbba18af9a36df747d6082c31036 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 10 Aug 2023 00:30:06 +0800 Subject: [PATCH 030/103] restore the label name --- openpype/hosts/max/plugins/load/load_pointcache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 24bcf58582..f250377cfd 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -14,7 +14,7 @@ class AbcLoader(load.LoaderPlugin): """Alembic loader.""" families = ["camera", "animation", "pointcache"] - label = "Load Alembic with Max" + label = "Load Alembic" representations = ["abc"] order = -10 icon = "code-fork" From 0a69439f2ef257e9800eda5e88d925b258f2ee25 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 10 Aug 2023 01:00:34 +0800 Subject: [PATCH 031/103] supports loading ornatrix alembic --- .../max/plugins/load/load_model_ornatrix.py | 74 +++++++++++++++++++ .../plugins/load/load_pointcache_ornatrix.py | 70 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 openpype/hosts/max/plugins/load/load_model_ornatrix.py create mode 100644 openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py new file mode 100644 index 0000000000..92773ad567 --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_model_ornatrix.py @@ -0,0 +1,74 @@ +import os +from openpype.pipeline import load, get_representation_path +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class OxModelAbcLoader(load.LoaderPlugin): + """Loading model with the Ornatrix Alembic loader.""" + + families = ["model"] + label = "Load Model with Ornatrix Alembic" + representations = ["abc"] + order = -10 + icon = "code-fork" + color = "orange" + + def load(self, context, name=None, namespace=None, data=None): + from pymxs import runtime as rt + + file_path = os.path.normpath(self.filepath_from_context(context)) + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = True + rt.AlembicImport.CustomAttributes = True + rt.AlembicImport.UVs = True + rt.AlembicImport.VertexColors = True + rt.importFile(file_path, rt.name("noPrompt")) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + abc_container = rt.Container(name=name) + for abc in scene_object_after: + abc.Parent = abc_container + + return containerise( + name, [abc_container], context, loader=self.__class__.__name__ + ) + + def update(self, container, representation): + from pymxs import runtime as rt + + path = get_representation_path(representation) + node_name = container["instance_node"] + instance_name, _ = os.path.splitext(node_name) + container = rt.getNodeByName(instance_name) + for children in container.Children: + rt.Delete(children) + + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = True + rt.AlembicImport.CustomAttributes = True + rt.AlembicImport.UVs = True + rt.AlembicImport.VertexColors = True + rt.importFile(path) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + for scene_object in scene_object_after: + scene_object.Parent = container + + lib.imprint( + container["instance_node"], + {"representation": str(representation["_id"])}, + ) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + from pymxs import runtime as rt + + node = rt.GetNodeByName(container["instance_node"]) + rt.Delete(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py new file mode 100644 index 0000000000..cd08e9a2ff --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -0,0 +1,70 @@ +import os +from openpype.pipeline import load, get_representation_path +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class OxAbcLoader(load.LoaderPlugin): + """Ornatrix Alembic loader.""" + + families = ["camera", "animation", "pointcache"] + label = "Load Alembic with Ornatrix" + representations = ["abc"] + order = -10 + icon = "code-fork" + color = "orange" + + def load(self, context, name=None, namespace=None, data=None): + from pymxs import runtime as rt + + file_path = os.path.normpath(self.filepath_from_context(context)) + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = True + rt.AlembicImport.CustomAttributes = True + rt.importFile(file_path, rt.name("noPrompt")) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + abc_container = rt.Container(name=name) + for abc in scene_object_after: + abc.Parent = abc_container + + return containerise( + name, [abc_container], context, loader=self.__class__.__name__ + ) + + def update(self, container, representation): + from pymxs import runtime as rt + + path = get_representation_path(representation) + node_name = container["instance_node"] + instance_name, _ = os.path.splitext(node_name) + container = rt.getNodeByName(instance_name) + for children in container.Children: + rt.Delete(children) + + scene_object_before = [obj for obj in rt.rootNode.Children] + rt.AlembicImport.ImportToRoot = False + rt.AlembicImport.CustomAttributes = True + rt.importFile(path) + scene_object_after = [obj for obj in rt.rootNode.Children] + for scene_object in scene_object_before: + scene_object_after = scene_object_after.remove(scene_object) + + for scene_object in scene_object_after: + scene_object.Parent = container + + lib.imprint( + container["instance_node"], + {"representation": str(representation["_id"])}, + ) + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + from pymxs import runtime as rt + + node = rt.GetNodeByName(container["instance_node"]) + rt.Delete(node) From 17904600a00dbb64875ce06fd07d3d6d220ec8ca Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 10 Aug 2023 14:56:23 +0800 Subject: [PATCH 032/103] add using ornatrix alembic importer into the ornatrix alembic loaders --- openpype/hosts/max/plugins/load/load_model_ornatrix.py | 4 +++- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py index 92773ad567..38c081b91c 100644 --- a/openpype/hosts/max/plugins/load/load_model_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_model_ornatrix.py @@ -23,7 +23,9 @@ class OxModelAbcLoader(load.LoaderPlugin): rt.AlembicImport.CustomAttributes = True rt.AlembicImport.UVs = True rt.AlembicImport.VertexColors = True - rt.importFile(file_path, rt.name("noPrompt")) + rt.importFile( + file_path, rt.name("noPrompt"), + using=rt.Ornatrix_Alembic_Importer) scene_object_after = [obj for obj in rt.rootNode.Children] for scene_object in scene_object_before: scene_object_after = scene_object_after.remove(scene_object) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index cd08e9a2ff..65a8273ab5 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -21,7 +21,9 @@ class OxAbcLoader(load.LoaderPlugin): scene_object_before = [obj for obj in rt.rootNode.Children] rt.AlembicImport.ImportToRoot = True rt.AlembicImport.CustomAttributes = True - rt.importFile(file_path, rt.name("noPrompt")) + rt.importFile( + file_path, rt.name("noPrompt"), + using=rt.Ornatrix_Alembic_Importer) scene_object_after = [obj for obj in rt.rootNode.Children] for scene_object in scene_object_before: scene_object_after = scene_object_after.remove(scene_object) From a3c761c0683c25ab5f4a901d06a3f955ffcd8d10 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 10 Aug 2023 15:36:59 +0800 Subject: [PATCH 033/103] add using ornatrix alembic importer into the ornatrix alembic loaders when updating version --- openpype/hosts/max/plugins/load/load_model_ornatrix.py | 4 +++- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py index 38c081b91c..07633ec55d 100644 --- a/openpype/hosts/max/plugins/load/load_model_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_model_ornatrix.py @@ -53,7 +53,9 @@ class OxModelAbcLoader(load.LoaderPlugin): rt.AlembicImport.CustomAttributes = True rt.AlembicImport.UVs = True rt.AlembicImport.VertexColors = True - rt.importFile(path) + rt.importFile( + path, rt.name("noPrompt"), + using=rt.Ornatrix_Alembic_Importer) scene_object_after = [obj for obj in rt.rootNode.Children] for scene_object in scene_object_before: scene_object_after = scene_object_after.remove(scene_object) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 65a8273ab5..f783583ff1 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -49,7 +49,9 @@ class OxAbcLoader(load.LoaderPlugin): scene_object_before = [obj for obj in rt.rootNode.Children] rt.AlembicImport.ImportToRoot = False rt.AlembicImport.CustomAttributes = True - rt.importFile(path) + rt.importFile( + path, rt.name("noPrompt"), + using=rt.Ornatrix_Alembic_Importer) scene_object_after = [obj for obj in rt.rootNode.Children] for scene_object in scene_object_before: scene_object_after = scene_object_after.remove(scene_object) From f79f0c44da2e486887f0078c7e3d4dcfa2d4e007 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 11 Aug 2023 12:27:09 +0200 Subject: [PATCH 034/103] Add to cleanup files Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../hosts/maya/plugins/publish/extract_active_view_thumbnail.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py index cb039cbf51..b4e62f8acc 100644 --- a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py @@ -46,5 +46,6 @@ class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): image.writeToFile(path, "jpg") self.log.debug("Generated thumbnail: {}".format(path)) + context.data["cleanupFullPaths"].append(path) context.data[cache_key] = path return context.data[cache_key] From ef58284bceb6bff2a6ee965bc456600d821e80a8 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 22 Aug 2023 11:30:45 +0100 Subject: [PATCH 035/103] Respect persistent dir on Deadline. --- openpype/plugins/publish/collect_rendered_files.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/plugins/publish/collect_rendered_files.py b/openpype/plugins/publish/collect_rendered_files.py index 4b95d8ac44..dc54e296e1 100644 --- a/openpype/plugins/publish/collect_rendered_files.py +++ b/openpype/plugins/publish/collect_rendered_files.py @@ -103,13 +103,16 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): # stash render job id for later validation instance.data["render_job_id"] = data.get("job").get("_id") - + staging_dir_persistent = instance.data.get( + "stagingDir_persistent", False + ) representations = [] for repre_data in instance_data.get("representations") or []: self._fill_staging_dir(repre_data, anatomy) representations.append(repre_data) - add_repre_files_for_cleanup(instance, repre_data) + if not staging_dir_persistent: + add_repre_files_for_cleanup(instance, repre_data) instance.data["representations"] = representations @@ -124,7 +127,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): self.log.info( f"Adding audio to instance: {instance.data['audio']}") - return instance.data.get("stagingDir_persistent", False) + return staging_dir_persistent def process(self, context): self._context = context From 1157971186c8b364afa03a6081246b8bca41abb9 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 28 Aug 2023 18:55:49 +0800 Subject: [PATCH 036/103] ornatrix is a fur modifier so no loading model for ornatrix abc --- .../max/plugins/load/load_model_ornatrix.py | 78 ------------------- 1 file changed, 78 deletions(-) delete mode 100644 openpype/hosts/max/plugins/load/load_model_ornatrix.py diff --git a/openpype/hosts/max/plugins/load/load_model_ornatrix.py b/openpype/hosts/max/plugins/load/load_model_ornatrix.py deleted file mode 100644 index 07633ec55d..0000000000 --- a/openpype/hosts/max/plugins/load/load_model_ornatrix.py +++ /dev/null @@ -1,78 +0,0 @@ -import os -from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise -from openpype.hosts.max.api import lib - - -class OxModelAbcLoader(load.LoaderPlugin): - """Loading model with the Ornatrix Alembic loader.""" - - families = ["model"] - label = "Load Model with Ornatrix Alembic" - representations = ["abc"] - order = -10 - icon = "code-fork" - color = "orange" - - def load(self, context, name=None, namespace=None, data=None): - from pymxs import runtime as rt - - file_path = os.path.normpath(self.filepath_from_context(context)) - scene_object_before = [obj for obj in rt.rootNode.Children] - rt.AlembicImport.ImportToRoot = True - rt.AlembicImport.CustomAttributes = True - rt.AlembicImport.UVs = True - rt.AlembicImport.VertexColors = True - rt.importFile( - file_path, rt.name("noPrompt"), - using=rt.Ornatrix_Alembic_Importer) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - - abc_container = rt.Container(name=name) - for abc in scene_object_after: - abc.Parent = abc_container - - return containerise( - name, [abc_container], context, loader=self.__class__.__name__ - ) - - def update(self, container, representation): - from pymxs import runtime as rt - - path = get_representation_path(representation) - node_name = container["instance_node"] - instance_name, _ = os.path.splitext(node_name) - container = rt.getNodeByName(instance_name) - for children in container.Children: - rt.Delete(children) - - scene_object_before = [obj for obj in rt.rootNode.Children] - rt.AlembicImport.ImportToRoot = True - rt.AlembicImport.CustomAttributes = True - rt.AlembicImport.UVs = True - rt.AlembicImport.VertexColors = True - rt.importFile( - path, rt.name("noPrompt"), - using=rt.Ornatrix_Alembic_Importer) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - - for scene_object in scene_object_after: - scene_object.Parent = container - - lib.imprint( - container["instance_node"], - {"representation": str(representation["_id"])}, - ) - - def switch(self, container, representation): - self.update(container, representation) - - def remove(self, container): - from pymxs import runtime as rt - - node = rt.GetNodeByName(container["instance_node"]) - rt.Delete(node) From 749e8911f5f1a8ce00ce8e3d024004d3fb13c832 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 28 Aug 2023 23:20:43 +0800 Subject: [PATCH 037/103] make sure ornatrix loader would raise runtime error if the user doesn't have the plugin installed --- .../plugins/load/load_pointcache_ornatrix.py | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index f783583ff1..1dce9aaa65 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -2,7 +2,7 @@ import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api.pipeline import containerise from openpype.hosts.max.api import lib - +from pymxs import runtime as rt class OxAbcLoader(load.LoaderPlugin): """Ornatrix Alembic loader.""" @@ -15,7 +15,10 @@ class OxAbcLoader(load.LoaderPlugin): color = "orange" def load(self, context, name=None, namespace=None, data=None): - from pymxs import runtime as rt + plugin_list = get_plugins() + if "ornatrix.dlo" not in plugin_list: + raise RuntimeError("Ornatrix plugin not " + "found/installed in Max yet..") file_path = os.path.normpath(self.filepath_from_context(context)) scene_object_before = [obj for obj in rt.rootNode.Children] @@ -37,8 +40,6 @@ class OxAbcLoader(load.LoaderPlugin): ) def update(self, container, representation): - from pymxs import runtime as rt - path = get_representation_path(representation) node_name = container["instance_node"] instance_name, _ = os.path.splitext(node_name) @@ -68,7 +69,17 @@ class OxAbcLoader(load.LoaderPlugin): self.update(container, representation) def remove(self, container): - from pymxs import runtime as rt - node = rt.GetNodeByName(container["instance_node"]) rt.Delete(node) + + +def get_plugins() -> list: + """Get plugin list from 3ds max.""" + manager = rt.PluginManager + count = manager.pluginDllCount + plugin_info_list = [] + for p in range(1, count + 1): + plugin_info = manager.pluginDllName(p) + plugin_info_list.append(plugin_info) + + return plugin_info_list From d92f2bac2f0c4115500d48b3223f65eb7c052e7f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 28 Aug 2023 23:21:54 +0800 Subject: [PATCH 038/103] hound --- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 1dce9aaa65..5f7e0a05f8 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -4,6 +4,7 @@ from openpype.hosts.max.api.pipeline import containerise from openpype.hosts.max.api import lib from pymxs import runtime as rt + class OxAbcLoader(load.LoaderPlugin): """Ornatrix Alembic loader.""" From ad6d03cedae5c5b7bf8ed3ea8261383045f9383d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 29 Aug 2023 17:30:15 +0800 Subject: [PATCH 039/103] fix the playbacktype --- openpype/hosts/max/plugins/load/load_pointcache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index f250377cfd..3f8b241351 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -52,7 +52,7 @@ class AbcLoader(load.LoaderPlugin): for abc in rt.GetCurrentSelection(): for cam_shape in abc.Children: - cam_shape.playbackType = 2 + cam_shape.playbackType = 0 return containerise( name, [abc_container], context, loader=self.__class__.__name__ From 42d0b19b46d6c30e18b9dbaee00bba87fc7ea5fc Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 29 Aug 2023 17:37:12 +0800 Subject: [PATCH 040/103] add correct plugin name --- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 5f7e0a05f8..a3c9d94f83 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -17,7 +17,7 @@ class OxAbcLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): plugin_list = get_plugins() - if "ornatrix.dlo" not in plugin_list: + if "ephere.plugins.autodesk.max.ornatrix.dlo" not in plugin_list: raise RuntimeError("Ornatrix plugin not " "found/installed in Max yet..") From 7be680190f0cf97da06e02747b4a4c8ea9ff46fc Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 30 Aug 2023 17:29:53 +0800 Subject: [PATCH 041/103] bug fix on the ornatrix loader --- .../plugins/load/load_pointcache_ornatrix.py | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index a3c9d94f83..56cac00aeb 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -22,18 +22,20 @@ class OxAbcLoader(load.LoaderPlugin): "found/installed in Max yet..") file_path = os.path.normpath(self.filepath_from_context(context)) - scene_object_before = [obj for obj in rt.rootNode.Children] rt.AlembicImport.ImportToRoot = True rt.AlembicImport.CustomAttributes = True rt.importFile( file_path, rt.name("noPrompt"), using=rt.Ornatrix_Alembic_Importer) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) + + scene_object = [] + for obj in rt.rootNode.Children: + obj_type = rt.ClassOf(obj) + if str(obj_type).startswith("Ox_"): + scene_object.append(obj) abc_container = rt.Container(name=name) - for abc in scene_object_after: + for abc in scene_object: abc.Parent = abc_container return containerise( @@ -48,18 +50,20 @@ class OxAbcLoader(load.LoaderPlugin): for children in container.Children: rt.Delete(children) - scene_object_before = [obj for obj in rt.rootNode.Children] rt.AlembicImport.ImportToRoot = False rt.AlembicImport.CustomAttributes = True rt.importFile( path, rt.name("noPrompt"), using=rt.Ornatrix_Alembic_Importer) - scene_object_after = [obj for obj in rt.rootNode.Children] - for scene_object in scene_object_before: - scene_object_after = scene_object_after.remove(scene_object) - for scene_object in scene_object_after: - scene_object.Parent = container + scene_object = [] + for obj in rt.rootNode.Children: + obj_type = rt.ClassOf(obj) + if str(obj_type).startswith("Ox_"): + scene_object.append(obj) + + for abc in scene_object: + abc.Parent = container lib.imprint( container["instance_node"], From 8440d65949e76dd9aca42206df528a62625ea32b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 4 Sep 2023 20:32:16 +0800 Subject: [PATCH 042/103] update on the ornatrix laoder --- openpype/hosts/max/api/pipeline.py | 51 ------------------- .../plugins/load/load_pointcache_ornatrix.py | 46 ++++++++++++++--- 2 files changed, 38 insertions(+), 59 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index d9a66c60f5..2ce96d16e1 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -15,10 +15,8 @@ from openpype.pipeline import ( ) from openpype.hosts.max.api.menu import OpenPypeMenu from openpype.hosts.max.api import lib -from openpype.hosts.max.api.plugin import MS_CUSTOM_ATTRIB from openpype.hosts.max import MAX_HOST_DIR - from pymxs import runtime as rt # noqa log = logging.getLogger("openpype.hosts.max") @@ -173,52 +171,3 @@ def containerise(name: str, nodes: list, context, if not lib.imprint(container_name, data): print(f"imprinting of {container_name} failed.") return container - - -def load_custom_attribute_data(): - """Re-loading the Openpype/AYON custom parameter built by the creator - - Returns: - attribute: re-loading the custom OP attributes set in Maxscript - """ - return rt.Execute(MS_CUSTOM_ATTRIB) - - -def import_custom_attribute_data(container: str, selections: list): - """Importing the Openpype/AYON custom parameter built by the creator - - Args: - container (str): target container which adds custom attributes - selections (list): nodes to be added into - group in custom attributes - """ - attrs = load_custom_attribute_data() - modifier = rt.EmptyModifier() - rt.addModifier(container, modifier) - container.modifiers[0].name = "OP Data" - rt.custAttributes.add(container.modifiers[0], attrs) - nodes = {} - for i in selections: - nodes = { - str(i): rt.NodeTransformMonitor(node=i), - } - # Setting the property - rt.setProperty( - container.modifiers[0].openPypeData, - "all_handles", nodes.values()) - rt.setProperty( - container.modifiers[0].openPypeData, - "sel_list", nodes.keys()) - - -def update_custom_attribute_data(container: str, selections: list): - """Updating the Openpype/AYON custom parameter built by the creator - - Args: - container (str): target container which adds custom attributes - selections (list): nodes to be added into - group in custom attributes - """ - if container.modifiers[0].name == "OP Data": - rt.deleteModifier(container, container.modifiers[0]) - import_custom_attribute_data(container, selections) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 56cac00aeb..d3b7c61ff8 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -1,6 +1,15 @@ import os from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import ( + containerise, + import_custom_attribute_data, + update_custom_attribute_data +) +from openpype.hosts.max.api.lib import ( + unique_namespace, + get_namespace, + object_transform_set +) from openpype.hosts.max.api import lib from pymxs import runtime as rt @@ -14,6 +23,7 @@ class OxAbcLoader(load.LoaderPlugin): order = -10 icon = "code-fork" color = "orange" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): plugin_list = get_plugins() @@ -34,21 +44,37 @@ class OxAbcLoader(load.LoaderPlugin): if str(obj_type).startswith("Ox_"): scene_object.append(obj) - abc_container = rt.Container(name=name) + namespace = unique_namespace( + name + "_", + suffix="_", + ) + + abc_container = rt.Container() for abc in scene_object: abc.Parent = abc_container + abc.name = f"{namespace}:{abc.name}" + # rename the abc container with namespace + abc_container_name = f"{namespace}:{name}_{self.postfix}" + abc_container.name = abc_container_name + import_custom_attribute_data( + abc_container, abc_container.Children) return containerise( - name, [abc_container], context, loader=self.__class__.__name__ + name, [abc_container], context, + namespace, loader=self.__class__.__name__ ) def update(self, container, representation): path = get_representation_path(representation) node_name = container["instance_node"] - instance_name, _ = os.path.splitext(node_name) - container = rt.getNodeByName(instance_name) - for children in container.Children: - rt.Delete(children) + namespace, name = get_namespace(node_name) + sub_node_name = f"{namespace}:{name}_{self.postfix}" + inst_container = rt.getNodeByName(sub_node_name) + rt.Select(inst_container.Children) + transform_data = object_transform_set(inst_container.Children) + for prev_obj in rt.selection: + if rt.isValidNode(prev_obj): + rt.Delete(prev_obj) rt.AlembicImport.ImportToRoot = False rt.AlembicImport.CustomAttributes = True @@ -61,9 +87,13 @@ class OxAbcLoader(load.LoaderPlugin): obj_type = rt.ClassOf(obj) if str(obj_type).startswith("Ox_"): scene_object.append(obj) - + update_custom_attribute_data( + inst_container, scene_object.Children) for abc in scene_object: abc.Parent = container + abc.name = f"{namespace}:{abc.name}" + abc.pos = transform_data[f"{abc.name}.transform"] + abc.scale = transform_data[f"{abc.name}.scale"] lib.imprint( container["instance_node"], From 6c1385e2c94e263f9186609c272ab7c0503485d9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 4 Sep 2023 23:49:54 +0200 Subject: [PATCH 043/103] Inherit from correct new style creator --- .../hosts/maya/plugins/create/create_multiverse_usd_over.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/create/create_multiverse_usd_over.py b/openpype/hosts/maya/plugins/create/create_multiverse_usd_over.py index e1534dd68c..166dbf6515 100644 --- a/openpype/hosts/maya/plugins/create/create_multiverse_usd_over.py +++ b/openpype/hosts/maya/plugins/create/create_multiverse_usd_over.py @@ -6,7 +6,7 @@ from openpype.lib import ( ) -class CreateMultiverseUsdOver(plugin.Creator): +class CreateMultiverseUsdOver(plugin.MayaCreator): """Create Multiverse USD Override""" identifier = "io.openpype.creators.maya.mvusdoverride" From 8ceedd7b60c58bf94cc1721f033bff89c0a2b121 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 17:56:09 +0200 Subject: [PATCH 044/103] Draft for implementing a native Maya USD creator next to the Multiverse USD creator --- openpype/hosts/maya/api/plugin.py | 35 ++++ .../maya/plugins/create/create_maya_usd.py | 143 +++++++++++++++ .../plugins/create/create_multiverse_usd.py | 4 + .../hosts/maya/plugins/load/load_maya_usd.py | 100 +++++++++++ .../maya/plugins/publish/extract_maya_usd.py | 168 ++++++++++++++++++ .../plugins/publish/extract_multiverse_usd.py | 2 +- 6 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/maya/plugins/create/create_maya_usd.py create mode 100644 openpype/hosts/maya/plugins/load/load_maya_usd.py create mode 100644 openpype/hosts/maya/plugins/publish/extract_maya_usd.py diff --git a/openpype/hosts/maya/api/plugin.py b/openpype/hosts/maya/api/plugin.py index 3f383fafb8..058637c8b5 100644 --- a/openpype/hosts/maya/api/plugin.py +++ b/openpype/hosts/maya/api/plugin.py @@ -129,12 +129,34 @@ class MayaCreatorBase(object): shared_data["maya_cached_legacy_subsets"] = cache_legacy return shared_data + def get_publish_families(self): + """Return families for the instances of this creator. + + Allow a Creator to define multiple families so that a creator can + e.g. specify `usd` and `usdMaya` and another USD creator can also + specify `usd` but apply different extractors like `usdMultiverse`. + + There is no need to override this method if you only have the + primary family defined by the `family` property as that will always + be set. + + Returns: + list: families for instances of this creator + + """ + return [] + def imprint_instance_node(self, node, data): # We never store the instance_node as value on the node since # it's the node name itself data.pop("instance_node", None) + # Don't store `families` since it's up to the creator itself + # to define the initial publish families - not a stored attribute of + # `families` + data.pop("families", None) + # We store creator attributes at the root level and assume they # will not clash in names with `subset`, `task`, etc. and other # default names. This is just so these attributes in many cases @@ -186,6 +208,11 @@ class MayaCreatorBase(object): # Explicitly re-parse the node name node_data["instance_node"] = node + # If the creator plug-in specifies + families = self.get_publish_families() + if families: + node_data["families"] = families + return node_data def _default_collect_instances(self): @@ -230,6 +257,14 @@ class MayaCreator(NewCreator, MayaCreatorBase): if pre_create_data.get("use_selection"): members = cmds.ls(selection=True) + # Allow a Creator to define multiple families + publish_families = self.get_publish_families() + if publish_families: + families = instance_data.setdefault("families", []) + for family in self.get_publish_families(): + if family not in families: + families.append(family) + with lib.undo_chunk(): instance_node = cmds.sets(members, name=subset_name) instance_data["instance_node"] = instance_node diff --git a/openpype/hosts/maya/plugins/create/create_maya_usd.py b/openpype/hosts/maya/plugins/create/create_maya_usd.py new file mode 100644 index 0000000000..298dc6a24f --- /dev/null +++ b/openpype/hosts/maya/plugins/create/create_maya_usd.py @@ -0,0 +1,143 @@ +from openpype.hosts.maya.api import plugin, lib +from openpype.lib import ( + BoolDef, + NumberDef, + TextDef, + EnumDef +) + + +class CreateMayaUsd(plugin.MayaCreator): + """Create Maya USD Export""" + + identifier = "io.openpype.creators.maya.mayausd" + label = "Maya USD" + family = "usd" + icon = "cubes" + description = "Create Maya USD Export" + + def get_publish_families(self): + return ["usd", "mayaUsd"] + + def get_instance_attr_defs(self): + + defs = lib.collect_animation_defs() + defs.extend([ + EnumDef("defaultUSDFormat", + label="File format", + items={ + "usdc": "Binary", + "usda": "ASCII" + }, + default="usdc"), + BoolDef("stripNamespaces", + label="Strip Namespaces", + default=True), + BoolDef("mergeTransformAndShape", + label="Merge Transform and Shape", + default=True), + # BoolDef("writeAncestors", + # label="Write Ancestors", + # default=True), + # BoolDef("flattenParentXforms", + # label="Flatten Parent Xforms", + # default=False), + # BoolDef("writeSparseOverrides", + # label="Write Sparse Overrides", + # default=False), + # BoolDef("useMetaPrimPath", + # label="Use Meta Prim Path", + # default=False), + # TextDef("customRootPath", + # label="Custom Root Path", + # default=''), + # TextDef("customAttributes", + # label="Custom Attributes", + # tooltip="Comma-separated list of attribute names", + # default=''), + # TextDef("nodeTypesToIgnore", + # label="Node Types to Ignore", + # tooltip="Comma-separated list of node types to be ignored", + # default=''), + # BoolDef("writeMeshes", + # label="Write Meshes", + # default=True), + # BoolDef("writeCurves", + # label="Write Curves", + # default=True), + # BoolDef("writeParticles", + # label="Write Particles", + # default=True), + # BoolDef("writeCameras", + # label="Write Cameras", + # default=False), + # BoolDef("writeLights", + # label="Write Lights", + # default=False), + # BoolDef("writeJoints", + # label="Write Joints", + # default=False), + # BoolDef("writeCollections", + # label="Write Collections", + # default=False), + # BoolDef("writePositions", + # label="Write Positions", + # default=True), + # BoolDef("writeNormals", + # label="Write Normals", + # default=True), + # BoolDef("writeUVs", + # label="Write UVs", + # default=True), + # BoolDef("writeColorSets", + # label="Write Color Sets", + # default=False), + # BoolDef("writeTangents", + # label="Write Tangents", + # default=False), + # BoolDef("writeRefPositions", + # label="Write Ref Positions", + # default=True), + # BoolDef("writeBlendShapes", + # label="Write BlendShapes", + # default=False), + # BoolDef("writeDisplayColor", + # label="Write Display Color", + # default=True), + # BoolDef("writeSkinWeights", + # label="Write Skin Weights", + # default=False), + # BoolDef("writeMaterialAssignment", + # label="Write Material Assignment", + # default=False), + # BoolDef("writeHardwareShader", + # label="Write Hardware Shader", + # default=False), + # BoolDef("writeShadingNetworks", + # label="Write Shading Networks", + # default=False), + # BoolDef("writeTransformMatrix", + # label="Write Transform Matrix", + # default=True), + # BoolDef("writeUsdAttributes", + # label="Write USD Attributes", + # default=True), + # BoolDef("writeInstancesAsReferences", + # label="Write Instances as References", + # default=False), + # BoolDef("timeVaryingTopology", + # label="Time Varying Topology", + # default=False), + # TextDef("customMaterialNamespace", + # label="Custom Material Namespace", + # default=''), + # NumberDef("numTimeSamples", + # label="Num Time Samples", + # default=1), + # NumberDef("timeSamplesSpan", + # label="Time Samples Span", + # default=0.0), + # + ]) + + return defs diff --git a/openpype/hosts/maya/plugins/create/create_multiverse_usd.py b/openpype/hosts/maya/plugins/create/create_multiverse_usd.py index 0b0ad3bccb..2963d4d5b6 100644 --- a/openpype/hosts/maya/plugins/create/create_multiverse_usd.py +++ b/openpype/hosts/maya/plugins/create/create_multiverse_usd.py @@ -14,6 +14,10 @@ class CreateMultiverseUsd(plugin.MayaCreator): label = "Multiverse USD Asset" family = "usd" icon = "cubes" + description = "Create Multiverse USD Asset" + + def get_publish_families(self): + return ["usd", "mvUsd"] def get_instance_attr_defs(self): diff --git a/openpype/hosts/maya/plugins/load/load_maya_usd.py b/openpype/hosts/maya/plugins/load/load_maya_usd.py new file mode 100644 index 0000000000..26c497768d --- /dev/null +++ b/openpype/hosts/maya/plugins/load/load_maya_usd.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +import maya.cmds as cmds + +from openpype.pipeline import ( + load, + get_representation_path, +) +from openpype.pipeline.load import get_representation_path_from_context +from openpype.hosts.maya.api.lib import ( + namespaced, + unique_namespace +) +from openpype.hosts.maya.api.pipeline import containerise + + +class MayaUsdLoader(load.LoaderPlugin): + """Read USD data in a Maya USD Proxy""" + + families = ["model", "usd", "pointcache", "animation"] + representations = ["usd", "usda", "usdc", "usdz", "abc"] + + label = "Load USD to Maya Proxy" + order = -1 + icon = "code-fork" + color = "orange" + + def load(self, context, name=None, namespace=None, options=None): + asset = context['asset']['name'] + namespace = namespace or unique_namespace( + asset + "_", + prefix="_" if asset[0].isdigit() else "", + suffix="_", + ) + + # Make sure we can load the plugin + cmds.loadPlugin("mayaUsdPlugin", quiet=True) + + path = get_representation_path_from_context(context) + + # Create the shape + cmds.namespace(addNamespace=namespace) + with namespaced(namespace, new=False): + transform = cmds.createNode("transform", + name=name, + skipSelect=True) + proxy = cmds.createNode('mayaUsdProxyShape', + name="{}Shape".format(name), + parent=transform, + skipSelect=True) + + cmds.connectAttr("time1.outTime", "{}.time".format(proxy)) + cmds.setAttr("{}.filePath".format(proxy), path, type="string") + + nodes = [transform, proxy] + self[:] = nodes + + return containerise( + name=name, + namespace=namespace, + nodes=nodes, + context=context, + loader=self.__class__.__name__) + + def update(self, container, representation): + # type: (dict, dict) -> None + """Update container with specified representation.""" + node = container['objectName'] + assert cmds.objExists(node), "Missing container" + + members = cmds.sets(node, query=True) or [] + shapes = cmds.ls(members, type="mayaUsdProxyShape") + + path = get_representation_path(representation) + for shape in shapes: + cmds.setAttr("{}.filePath".format(shape), path, type="string") + + cmds.setAttr("{}.representation".format(node), + str(representation["_id"]), + type="string") + + def switch(self, container, representation): + self.update(container, representation) + + def remove(self, container): + # type: (dict) -> None + """Remove loaded container.""" + # Delete container and its contents + if cmds.objExists(container['objectName']): + members = cmds.sets(container['objectName'], query=True) or [] + cmds.delete([container['objectName']] + members) + + # Remove the namespace, if empty + namespace = container['namespace'] + if cmds.namespace(exists=namespace): + members = cmds.namespaceInfo(namespace, listNamespace=True) + if not members: + cmds.namespace(removeNamespace=namespace) + else: + self.log.warning("Namespace not deleted because it " + "still has members: %s", namespace) diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py new file mode 100644 index 0000000000..3b95037d4c --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -0,0 +1,168 @@ +import os +import six + +from maya import cmds + +import pyblish.api +from openpype.pipeline import publish +from openpype.hosts.maya.api.lib import maintained_selection + + +class ExtractMayaUsd(publish.Extractor): + """Extractor for Maya USD Asset data. + + Upon publish a .usd (or .usdz) asset file will typically be written. + """ + + label = "Extract Maya USD Asset" + hosts = ["maya"] + families = ["mayaUsd"] + + @property + def options(self): + """Overridable options for Maya USD Export + + Given in the following format + - {NAME: EXPECTED TYPE} + + If the overridden option's type does not match, + the option is not included and a warning is logged. + + """ + + # TODO: Support more `mayaUSDExport` parameters + return { + "stripNamespaces": bool, + "mergeTransformAndShape": bool, + "exportDisplayColor": bool, + "exportColorSets": bool, + "exportInstances": bool, + "exportUVs": bool, + "exportVisibility": bool, + "exportComponentTags": bool, + "exportRefsAsInstanceable": bool, + "eulerFilter": bool, + "renderableOnly": bool, + #"worldspace": bool, + } + + @property + def default_options(self): + """The default options for Maya USD Export.""" + + # TODO: Support more `mayaUSDExport` parameters + return { + "stripNamespaces": False, + "mergeTransformAndShape": False, + "exportDisplayColor": False, + "exportColorSets": True, + "exportInstances": True, + "exportUVs": True, + "exportVisibility": True, + "exportComponentTags": True, + "exportRefsAsInstanceable": False, + "eulerFilter": True, + "renderableOnly": False, + #"worldspace": False + } + + def parse_overrides(self, instance, options): + """Inspect data of instance to determine overridden options""" + + for key in instance.data: + if key not in self.options: + continue + + # Ensure the data is of correct type + value = instance.data[key] + if isinstance(value, six.text_type): + value = str(value) + if not isinstance(value, self.options[key]): + self.log.warning( + "Overridden attribute {key} was of " + "the wrong type: {invalid_type} " + "- should have been {valid_type}".format( + key=key, + invalid_type=type(value).__name__, + valid_type=self.options[key].__name__)) + continue + + options[key] = value + + return options + + def filter_members(self, members): + # Can be overridden by inherited classes + return members + + def process(self, instance): + + # Load plugin first + cmds.loadPlugin("mayaUsdPlugin", quiet=True) + + # Define output file path + staging_dir = self.staging_dir(instance) + file_name = "{0}.usd".format(instance.name) + file_path = os.path.join(staging_dir, file_name) + file_path = file_path.replace('\\', '/') + + # Parse export options + options = self.default_options + options = self.parse_overrides(instance, options) + self.log.info("Export options: {0}".format(options)) + + # Perform extraction + self.log.debug("Performing extraction ...") + + members = instance.data("setMembers") + self.log.debug('Collected objects: {}'.format(members)) + members = self.filter_members(members) + if not members: + self.log.error('No members!') + return + + start = instance.data["frameStartHandle"] + end = instance.data["frameEndHandle"] + + with maintained_selection(): + self.log.debug('Exporting USD: {} / {}'.format(file_path, members)) + cmds.mayaUSDExport(file=file_path, + frameRange=(start, end), + frameStride=instance.data.get("step", 1.0), + exportRoots=members, + **options) + + representation = { + 'name': "usd", + 'ext': "usd", + 'files': file_name, + 'stagingDir': staging_dir + } + instance.data.setdefault("representations", []).append(representation) + + self.log.debug( + "Extracted instance {} to {}".format(instance.name, file_path) + ) + + +class ExtractMayaUsdAnim(ExtractMayaUsd): + """Extractor for Maya USD Animation Sparse Cache data. + + This will extract the sparse cache data from the scene and generate a + USD file with all the animation data. + + Upon publish a .usd sparse cache will be written. + """ + label = "Extract Maya USD Animation Sparse Cache" + families = ["animation", "mayaUsd"] + match = pyblish.api.Subset + + def filter_members(self, members): + out_set = next((i for i in members if i.endswith("out_SET")), None) + + if out_set is None: + self.log.warning("Expecting out_SET") + return None + + members = cmds.ls(cmds.sets(out_set, query=True), long=True) + return members diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py index 4399eacda1..e0a1369556 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py @@ -28,7 +28,7 @@ class ExtractMultiverseUsd(publish.Extractor): label = "Extract Multiverse USD Asset" hosts = ["maya"] - families = ["usd"] + families = ["mvUsd"] scene_type = "usd" file_formats = ["usd", "usda", "usdz"] From 90417a42c38e6197583969d2549de2b3b810568d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 17:56:30 +0200 Subject: [PATCH 045/103] Allow loading USD into Arnold Standin in Maya --- openpype/hosts/maya/plugins/load/load_arnold_standin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index b5cc4d629b..e1bd1954fa 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -32,8 +32,8 @@ def get_current_session_fps(): class ArnoldStandinLoader(load.LoaderPlugin): """Load as Arnold standin""" - families = ["ass", "animation", "model", "proxyAbc", "pointcache"] - representations = ["ass", "abc"] + families = ["ass", "animation", "model", "proxyAbc", "pointcache", "usd"] + representations = ["ass", "abc", "usda", "usdc", "usd"] label = "Load as Arnold standin" order = -5 From 4456ac86f41e7fa529b5f07d32da6e71f601128d Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 5 Sep 2023 17:56:49 +0200 Subject: [PATCH 046/103] :art: add default isort config --- setup.cfg | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 10cca3eb3f..216bae848f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,4 +28,11 @@ omit = /tests directory = ./coverage [tool:pytest] -norecursedirs = repos/* openpype/modules/ftrack/* \ No newline at end of file +norecursedirs = repos/* openpype/modules/ftrack/* + +[isort] +line_length = 79 +multi_line_output = 3 +include_trailing_comma = True +force_grid_wrap = 0 +combine_as_imports = True From 34b15587c11005ca9c2d7db77f44fa18ebb37f4e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 18:00:23 +0200 Subject: [PATCH 047/103] Cosmetics --- openpype/hosts/maya/plugins/load/load_arnold_standin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/plugins/load/load_arnold_standin.py b/openpype/hosts/maya/plugins/load/load_arnold_standin.py index e1bd1954fa..2e1329f201 100644 --- a/openpype/hosts/maya/plugins/load/load_arnold_standin.py +++ b/openpype/hosts/maya/plugins/load/load_arnold_standin.py @@ -17,6 +17,7 @@ from openpype.hosts.maya.api.lib import ( ) from openpype.hosts.maya.api.pipeline import containerise + def is_sequence(files): sequence = False collections, remainder = clique.assemble(files, minimum_items=1) @@ -29,6 +30,7 @@ def get_current_session_fps(): session_fps = float(legacy_io.Session.get('AVALON_FPS', 25)) return convert_to_maya_fps(session_fps) + class ArnoldStandinLoader(load.LoaderPlugin): """Load as Arnold standin""" From 5c12d9c8621130703d063ec5aba0fef832d479ac Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 18:04:21 +0200 Subject: [PATCH 048/103] Remove commented out attribute definitions --- .../maya/plugins/create/create_maya_usd.py | 106 +----------------- 1 file changed, 1 insertion(+), 105 deletions(-) diff --git a/openpype/hosts/maya/plugins/create/create_maya_usd.py b/openpype/hosts/maya/plugins/create/create_maya_usd.py index 298dc6a24f..554b8169db 100644 --- a/openpype/hosts/maya/plugins/create/create_maya_usd.py +++ b/openpype/hosts/maya/plugins/create/create_maya_usd.py @@ -1,8 +1,6 @@ from openpype.hosts.maya.api import plugin, lib from openpype.lib import ( BoolDef, - NumberDef, - TextDef, EnumDef ) @@ -35,109 +33,7 @@ class CreateMayaUsd(plugin.MayaCreator): default=True), BoolDef("mergeTransformAndShape", label="Merge Transform and Shape", - default=True), - # BoolDef("writeAncestors", - # label="Write Ancestors", - # default=True), - # BoolDef("flattenParentXforms", - # label="Flatten Parent Xforms", - # default=False), - # BoolDef("writeSparseOverrides", - # label="Write Sparse Overrides", - # default=False), - # BoolDef("useMetaPrimPath", - # label="Use Meta Prim Path", - # default=False), - # TextDef("customRootPath", - # label="Custom Root Path", - # default=''), - # TextDef("customAttributes", - # label="Custom Attributes", - # tooltip="Comma-separated list of attribute names", - # default=''), - # TextDef("nodeTypesToIgnore", - # label="Node Types to Ignore", - # tooltip="Comma-separated list of node types to be ignored", - # default=''), - # BoolDef("writeMeshes", - # label="Write Meshes", - # default=True), - # BoolDef("writeCurves", - # label="Write Curves", - # default=True), - # BoolDef("writeParticles", - # label="Write Particles", - # default=True), - # BoolDef("writeCameras", - # label="Write Cameras", - # default=False), - # BoolDef("writeLights", - # label="Write Lights", - # default=False), - # BoolDef("writeJoints", - # label="Write Joints", - # default=False), - # BoolDef("writeCollections", - # label="Write Collections", - # default=False), - # BoolDef("writePositions", - # label="Write Positions", - # default=True), - # BoolDef("writeNormals", - # label="Write Normals", - # default=True), - # BoolDef("writeUVs", - # label="Write UVs", - # default=True), - # BoolDef("writeColorSets", - # label="Write Color Sets", - # default=False), - # BoolDef("writeTangents", - # label="Write Tangents", - # default=False), - # BoolDef("writeRefPositions", - # label="Write Ref Positions", - # default=True), - # BoolDef("writeBlendShapes", - # label="Write BlendShapes", - # default=False), - # BoolDef("writeDisplayColor", - # label="Write Display Color", - # default=True), - # BoolDef("writeSkinWeights", - # label="Write Skin Weights", - # default=False), - # BoolDef("writeMaterialAssignment", - # label="Write Material Assignment", - # default=False), - # BoolDef("writeHardwareShader", - # label="Write Hardware Shader", - # default=False), - # BoolDef("writeShadingNetworks", - # label="Write Shading Networks", - # default=False), - # BoolDef("writeTransformMatrix", - # label="Write Transform Matrix", - # default=True), - # BoolDef("writeUsdAttributes", - # label="Write USD Attributes", - # default=True), - # BoolDef("writeInstancesAsReferences", - # label="Write Instances as References", - # default=False), - # BoolDef("timeVaryingTopology", - # label="Time Varying Topology", - # default=False), - # TextDef("customMaterialNamespace", - # label="Custom Material Namespace", - # default=''), - # NumberDef("numTimeSamples", - # label="Num Time Samples", - # default=1), - # NumberDef("timeSamplesSpan", - # label="Time Samples Span", - # default=0.0), - # + default=True) ]) return defs From d6f2ace99d87d2cb8069c02de72c6f7244a222bf Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 18:04:57 +0200 Subject: [PATCH 049/103] Cosmetics --- openpype/hosts/maya/plugins/publish/extract_maya_usd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py index 3b95037d4c..70508042c0 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -43,7 +43,7 @@ class ExtractMayaUsd(publish.Extractor): "exportRefsAsInstanceable": bool, "eulerFilter": bool, "renderableOnly": bool, - #"worldspace": bool, + # "worldspace": bool, } @property @@ -63,7 +63,7 @@ class ExtractMayaUsd(publish.Extractor): "exportRefsAsInstanceable": False, "eulerFilter": True, "renderableOnly": False, - #"worldspace": False + # "worldspace": False } def parse_overrides(self, instance, options): From 7f78a95559870a79f2b20c456ea4ec8a3419e30d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 22:04:38 +0200 Subject: [PATCH 050/103] Export correct file type (ascii vs binary) based on instance setting --- openpype/hosts/maya/plugins/publish/extract_maya_usd.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py index 70508042c0..32730d2963 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -32,6 +32,7 @@ class ExtractMayaUsd(publish.Extractor): # TODO: Support more `mayaUSDExport` parameters return { + "defaultUSDFormat": str, "stripNamespaces": bool, "mergeTransformAndShape": bool, "exportDisplayColor": bool, @@ -52,6 +53,7 @@ class ExtractMayaUsd(publish.Extractor): # TODO: Support more `mayaUSDExport` parameters return { + "defaultUSDFormat": "usdc", "stripNamespaces": False, "mergeTransformAndShape": False, "exportDisplayColor": False, From 93e3e310295c758f236e208dc7ed130eee4a4335 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 22:05:02 +0200 Subject: [PATCH 051/103] Log message as debug --- openpype/hosts/maya/plugins/publish/extract_maya_usd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py index 32730d2963..4a5fcc3366 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -111,7 +111,7 @@ class ExtractMayaUsd(publish.Extractor): # Parse export options options = self.default_options options = self.parse_overrides(instance, options) - self.log.info("Export options: {0}".format(options)) + self.log.debug("Export options: {0}".format(options)) # Perform extraction self.log.debug("Performing extraction ...") From f4a0ab45e4a9f50d60488fb8cfc7ccaae7f016a0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 23:10:32 +0200 Subject: [PATCH 052/103] Allow exporting custom attributes with `mayaUSDExport` --- .../maya/plugins/create/create_maya_usd.py | 16 ++- .../maya/plugins/publish/extract_maya_usd.py | 113 +++++++++++++++++- 2 files changed, 121 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/maya/plugins/create/create_maya_usd.py b/openpype/hosts/maya/plugins/create/create_maya_usd.py index 554b8169db..f05f155dd9 100644 --- a/openpype/hosts/maya/plugins/create/create_maya_usd.py +++ b/openpype/hosts/maya/plugins/create/create_maya_usd.py @@ -1,7 +1,8 @@ from openpype.hosts.maya.api import plugin, lib from openpype.lib import ( BoolDef, - EnumDef + EnumDef, + TextDef ) @@ -33,7 +34,18 @@ class CreateMayaUsd(plugin.MayaCreator): default=True), BoolDef("mergeTransformAndShape", label="Merge Transform and Shape", - default=True) + default=True), + BoolDef("includeUserDefinedAttributes", + label="Include User Defined Attributes", + default=False), + TextDef("attr", + label="Custom Attributes", + default="", + placeholder="attr1, attr2"), + TextDef("attrPrefix", + label="Custom Attributes Prefix", + default="", + placeholder="prefix1, prefix2") ]) return defs diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py index 4a5fcc3366..dfdea6868f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -1,5 +1,7 @@ import os import six +import json +import contextlib from maya import cmds @@ -8,6 +10,88 @@ from openpype.pipeline import publish from openpype.hosts.maya.api.lib import maintained_selection +@contextlib.contextmanager +def usd_export_attributes(nodes, attrs=None, attr_prefixes=None, mapping=None): + """Define attributes for the given nodes that should be exported. + + MayaUSDExport will export custom attributes if the Maya node has a + string attribute `USD_UserExportedAttributesJson` that provides an + export mapping for the maya attributes. This context manager will try + to autogenerate such an attribute during the export to include attributes + for the export. + + """ + # todo: this might be better done with a custom export chaser + # see `chaser` argument for `mayaUSDExport` + + import maya.api.OpenMaya as om + + if not attrs and not attr_prefixes: + # context manager does nothing + yield + return + + if attrs is None: + attrs = [] + if attr_prefixes is None: + attr_prefixes = [] + if mapping is None: + mapping = {} + + usd_json_attr = "USD_UserExportedAttributesJson" + strings = attrs + ["{}*".format(prefix) for prefix in attr_prefixes] + context_state = {} + for node in set(nodes): + node_attrs = cmds.listAttr(node, st=strings) + if not node_attrs: + # Nothing to do for this node + continue + + node_attr_data = {} + for node_attr in set(node_attrs): + node_attr_data[node_attr] = mapping.get(node_attr, {}) + + if cmds.attributeQuery(usd_json_attr, node=node, exists=True): + existing_node_attr_value = cmds.getAttr( + "{}.{}".format(node, usd_json_attr) + ) + if existing_node_attr_value and existing_node_attr_value != "{}": + # Any existing attribute mappings in an existing + # `USD_UserExportedAttributesJson` attribute always take + # precedence over what this function tries to imprint + existing_node_attr_data = json.loads(existing_node_attr_value) + node_attr_data.update(existing_node_attr_data) + + context_state[node] = json.dumps(node_attr_data) + + sel = om.MSelectionList() + dg_mod = om.MDGModifier() + fn_string = om.MFnStringData() + fn_typed = om.MFnTypedAttribute() + try: + for node, value in context_state.items(): + data = fn_string.create(value) + sel.clear() + if cmds.attributeQuery(usd_json_attr, node=node, exists=True): + # Set the attribute value + sel.add("{}.{}".format(node, usd_json_attr)) + plug = sel.getPlug(0) + dg_mod.newPlugValue(plug, data) + else: + # Create attribute with the value as default value + sel.add(node) + node_obj = sel.getDependNode(0) + attr_obj = fn_typed.create(usd_json_attr, + usd_json_attr, + om.MFnData.kString, + data) + dg_mod.addAttribute(node_obj, attr_obj) + dg_mod.doIt() + yield + finally: + dg_mod.undoIt() + + class ExtractMayaUsd(publish.Extractor): """Extractor for Maya USD Asset data. @@ -126,13 +210,30 @@ class ExtractMayaUsd(publish.Extractor): start = instance.data["frameStartHandle"] end = instance.data["frameEndHandle"] + def parse_attr_str(attr_str): + result = list() + for attr in attr_str.split(","): + attr = attr.strip() + if not attr: + continue + result.append(attr) + return result + + attrs = parse_attr_str(instance.data.get("attr", "")) + attrs += instance.data.get("userDefinedAttributes", []) + attrs += ["cbId"] + attr_prefixes = parse_attr_str(instance.data.get("attrPrefix", "")) + + self.log.debug('Exporting USD: {} / {}'.format(file_path, members)) with maintained_selection(): - self.log.debug('Exporting USD: {} / {}'.format(file_path, members)) - cmds.mayaUSDExport(file=file_path, - frameRange=(start, end), - frameStride=instance.data.get("step", 1.0), - exportRoots=members, - **options) + with usd_export_attributes(instance[:], + attrs=attrs, + attr_prefixes=attr_prefixes): + cmds.mayaUSDExport(file=file_path, + frameRange=(start, end), + frameStride=instance.data.get("step", 1.0), + exportRoots=members, + **options) representation = { 'name': "usd", From 17d494c1a2cb5229b764daeb415010f97fe46ad4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 23:13:39 +0200 Subject: [PATCH 053/103] Add logic to collect user defined attributes and merge logic with pointcache and animation family + optimize the query by doing only one `cmds.listAttr` call --- .../maya/plugins/publish/collect_animation.py | 14 ------- .../plugins/publish/collect_pointcache.py | 15 ------- .../collect_user_defined_attributes.py | 39 +++++++++++++++++++ 3 files changed, 39 insertions(+), 29 deletions(-) create mode 100644 openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py diff --git a/openpype/hosts/maya/plugins/publish/collect_animation.py b/openpype/hosts/maya/plugins/publish/collect_animation.py index 8f523f770b..26a0a01c8b 100644 --- a/openpype/hosts/maya/plugins/publish/collect_animation.py +++ b/openpype/hosts/maya/plugins/publish/collect_animation.py @@ -58,17 +58,3 @@ class CollectAnimationOutputGeometry(pyblish.api.InstancePlugin): if instance.data.get("farm"): instance.data["families"].append("publish.farm") - # Collect user defined attributes. - if not instance.data.get("includeUserDefinedAttributes", False): - return - - user_defined_attributes = set() - for node in hierarchy: - attrs = cmds.listAttr(node, userDefined=True) or list() - shapes = cmds.listRelatives(node, shapes=True) or list() - for shape in shapes: - attrs.extend(cmds.listAttr(shape, userDefined=True) or list()) - - user_defined_attributes.update(attrs) - - instance.data["userDefinedAttributes"] = list(user_defined_attributes) diff --git a/openpype/hosts/maya/plugins/publish/collect_pointcache.py b/openpype/hosts/maya/plugins/publish/collect_pointcache.py index bb9065792f..5578a57f31 100644 --- a/openpype/hosts/maya/plugins/publish/collect_pointcache.py +++ b/openpype/hosts/maya/plugins/publish/collect_pointcache.py @@ -45,18 +45,3 @@ class CollectPointcache(pyblish.api.InstancePlugin): if proxy_set: instance.remove(proxy_set) instance.data["setMembers"].remove(proxy_set) - - # Collect user defined attributes. - if not instance.data.get("includeUserDefinedAttributes", False): - return - - user_defined_attributes = set() - for node in instance: - attrs = cmds.listAttr(node, userDefined=True) or list() - shapes = cmds.listRelatives(node, shapes=True) or list() - for shape in shapes: - attrs.extend(cmds.listAttr(shape, userDefined=True) or list()) - - user_defined_attributes.update(attrs) - - instance.data["userDefinedAttributes"] = list(user_defined_attributes) diff --git a/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py b/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py new file mode 100644 index 0000000000..4d0790ad7c --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py @@ -0,0 +1,39 @@ +from maya import cmds + +import pyblish.api + + +class CollectUserDefinedAttributes(pyblish.api.InstancePlugin): + """Collect user defined attributes for nodes in instance.""" + + order = pyblish.api.CollectorOrder + 0.4 + families = ["pointcache", "animation", "usd"] + label = "Collect User Defined Attributes" + hosts = ["maya"] + + def process(self, instance): + + # Collect user defined attributes. + if not instance.data.get("includeUserDefinedAttributes", False): + return + + if "out_hierarchy" in instance.data: + # animation family + nodes = instance.data["out_hierarchy"] + else: + nodes = instance[:] + if not nodes: + return + + shapes = cmds.listRelatives(nodes, shapes=True, fullPath=True) or [] + nodes = set(nodes).union(shapes) + + attrs = cmds.listAttr(list(nodes), userDefined=True) or [] + user_defined_attributes = list(sorted(set(attrs))) + instance.data["userDefinedAttributes"] = user_defined_attributes + + self.log.debug( + "Collected user defined attributes: {}".format( + ", ".join(user_defined_attributes) + ) + ) From 4a861a6bfcdc06026fe4146e162523a1dc33cb58 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 23:29:46 +0200 Subject: [PATCH 054/103] Improve docstring --- .../maya/plugins/publish/extract_maya_usd.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py index dfdea6868f..09bbf01831 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -20,6 +20,26 @@ def usd_export_attributes(nodes, attrs=None, attr_prefixes=None, mapping=None): to autogenerate such an attribute during the export to include attributes for the export. + Arguments: + nodes (List[str]): Nodes to process. + attrs (Optional[List[str]]): Full name of attributes to include. + attr_prefixes (Optional[List[str]]): Prefixes of attributes to include. + mapping (Optional[Dict[Dict]]): A mapping per attribute name for the + conversion to a USD attribute, including renaming, defining type, + converting attribute precision, etc. This match the usual + `USD_UserExportedAttributesJson` json mapping of `mayaUSDExport`. + When no mapping provided for an attribute it will use `{}` as + value. + + Examples: + >>> with usd_export_attributes( + >>> ["pCube1"], attrs="myDoubleAttributeAsFloat", mapping={ + >>> "myDoubleAttributeAsFloat": { + >>> "usdAttrName": "my:namespace:attrib", + >>> "translateMayaDoubleToUsdSinglePrecision": True, + >>> } + >>> }) + """ # todo: this might be better done with a custom export chaser # see `chaser` argument for `mayaUSDExport` From a61f7ac7998453dad917d01e43fa134320a8e7e5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 00:02:39 +0200 Subject: [PATCH 055/103] Add support for Look Assigner to assign looks in `aiStandin` for USD files based on `cbId` attributes in the USD file. - For this to currently work the transform and shape should *not* be merged into a single Prim inside USD because otherwise the unique `cbId` between Transform and Shape node will be lost. --- .../tools/mayalookassigner/arnold_standin.py | 8 ++++ .../hosts/maya/tools/mayalookassigner/usd.py | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 openpype/hosts/maya/tools/mayalookassigner/usd.py diff --git a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py index 0ce2b21dcd..076b0047bb 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py +++ b/openpype/hosts/maya/tools/mayalookassigner/arnold_standin.py @@ -10,6 +10,7 @@ from openpype.client import get_last_version_by_subset_name from openpype.hosts.maya import api from . import lib from .alembic import get_alembic_ids_cache +from .usd import is_usd_lib_supported, get_usd_ids_cache log = logging.getLogger(__name__) @@ -74,6 +75,13 @@ def get_nodes_by_id(standin): # Support alembic files directly return get_alembic_ids_cache(path) + elif ( + is_usd_lib_supported and + any(path.endswith(ext) for ext in [".usd", ".usda", ".usdc"]) + ): + # Support usd files directly + return get_usd_ids_cache(path) + json_path = None for f in os.listdir(os.path.dirname(path)): if f.endswith(".json"): diff --git a/openpype/hosts/maya/tools/mayalookassigner/usd.py b/openpype/hosts/maya/tools/mayalookassigner/usd.py new file mode 100644 index 0000000000..beecbd531a --- /dev/null +++ b/openpype/hosts/maya/tools/mayalookassigner/usd.py @@ -0,0 +1,38 @@ +from collections import defaultdict + +try: + from pxr import Usd + is_usd_lib_supported = True +except ImportError: + is_usd_lib_supported = False + + +def get_usd_ids_cache(path): + # type: (str) -> dict + """Build a id to node mapping in a USD file. + + Nodes without IDs are ignored. + + Returns: + dict: Mapping of id to nodes in the USD file. + + """ + if not is_usd_lib_supported: + raise RuntimeError("No pxr.Usd python library available.") + + stage = Usd.Stage.Open(path) + ids = {} + for prim in stage.Traverse(): + attr = prim.GetAttribute("userProperties:cbId") + if not attr.IsValid(): + continue + path = str(prim.GetPath()) + value = attr.Get() + if not value: + continue + ids[path] = value + + cache = defaultdict(list) + for path, value in ids.items(): + cache[value].append(path) + return dict(cache) From b953391f43592fedf18069093c21e33a35136871 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 00:07:39 +0200 Subject: [PATCH 056/103] Only get path if a value is found --- openpype/hosts/maya/tools/mayalookassigner/usd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/tools/mayalookassigner/usd.py b/openpype/hosts/maya/tools/mayalookassigner/usd.py index beecbd531a..6b5cb2f0f5 100644 --- a/openpype/hosts/maya/tools/mayalookassigner/usd.py +++ b/openpype/hosts/maya/tools/mayalookassigner/usd.py @@ -26,10 +26,10 @@ def get_usd_ids_cache(path): attr = prim.GetAttribute("userProperties:cbId") if not attr.IsValid(): continue - path = str(prim.GetPath()) value = attr.Get() if not value: continue + path = str(prim.GetPath()) ids[path] = value cache = defaultdict(list) From 11cd5a874eee0877c16c9cfde8cb8b74f1630364 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 00:13:34 +0200 Subject: [PATCH 057/103] Make sure to run after `CollectPointcache` and `CollectAnimation` --- .../maya/plugins/publish/collect_user_defined_attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py b/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py index 4d0790ad7c..16fef2e168 100644 --- a/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py +++ b/openpype/hosts/maya/plugins/publish/collect_user_defined_attributes.py @@ -6,7 +6,7 @@ import pyblish.api class CollectUserDefinedAttributes(pyblish.api.InstancePlugin): """Collect user defined attributes for nodes in instance.""" - order = pyblish.api.CollectorOrder + 0.4 + order = pyblish.api.CollectorOrder + 0.45 families = ["pointcache", "animation", "usd"] label = "Collect User Defined Attributes" hosts = ["maya"] From 8f5b09af2110bf93169bc69f91989981e8f3ad99 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 6 Sep 2023 15:58:09 +0800 Subject: [PATCH 058/103] adding back the missing function after resolving conflict --- openpype/hosts/max/api/pipeline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index c4167dfe0a..23b89a9ac2 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -15,6 +15,7 @@ from openpype.pipeline import ( ) from openpype.hosts.max.api.menu import OpenPypeMenu from openpype.hosts.max.api import lib +from openpype.hosts.max.api.plugin import MS_CUSTOM_ATTRIB from openpype.hosts.max import MAX_HOST_DIR from pymxs import runtime as rt # noqa From 862907079c7c143854e864270878afb40449060e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 15:23:11 +0200 Subject: [PATCH 059/103] Support special creator attributes in Maya's flattened `creator_attributes` structure that are not convertable to Maya native attribute types (list, tuple, dict), like e.g. `EnumDef` with `multiselection=True` --- openpype/hosts/maya/api/plugin.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/api/plugin.py b/openpype/hosts/maya/api/plugin.py index 058637c8b5..770767fc7d 100644 --- a/openpype/hosts/maya/api/plugin.py +++ b/openpype/hosts/maya/api/plugin.py @@ -161,8 +161,17 @@ class MayaCreatorBase(object): # will not clash in names with `subset`, `task`, etc. and other # default names. This is just so these attributes in many cases # are still editable in the maya UI by artists. - # pop to move to end of dict to sort attributes last on the node + # note: pop to move to end of dict to sort attributes last on the node creator_attributes = data.pop("creator_attributes", {}) + + # We only flatten value types which `imprint` function supports + json_creator_attributes = {} + for key, value in dict(creator_attributes).items(): + if isinstance(value, (list, tuple, dict)): + creator_attributes.pop(key) + json_creator_attributes[key] = value + + # Flatten remaining creator attributes to the node itself data.update(creator_attributes) # We know the "publish_attributes" will be complex data of @@ -172,6 +181,10 @@ class MayaCreatorBase(object): data.pop("publish_attributes", {}) ) + # Persist the non-flattened creator attributes (special value types, + # like multiselection EnumDef) + data["creator_attributes"] = json.dumps(json_creator_attributes) + # Since we flattened the data structure for creator attributes we want # to correctly detect which flattened attributes should end back in the # creator attributes when reading the data from the node, so we store @@ -192,15 +205,22 @@ class MayaCreatorBase(object): # being read as 'data' node_data.pop("cbId", None) + # Make sure we convert any creator attributes from the json string + creator_attributes = node_data.get("creator_attributes") + if creator_attributes: + node_data["creator_attributes"] = json.loads(creator_attributes) + else: + node_data["creator_attributes"] = {} + # Move the relevant attributes into "creator_attributes" that # we flattened originally - node_data["creator_attributes"] = {} creator_attribute_keys = node_data.pop("__creator_attributes_keys", "").split(",") for key in creator_attribute_keys: if key in node_data: node_data["creator_attributes"][key] = node_data.pop(key) + # Make sure we convert any publish attributes from the json string publish_attributes = node_data.get("publish_attributes") if publish_attributes: node_data["publish_attributes"] = json.loads(publish_attributes) From 48ab18f5431a42bdd185f25a7bedab5b45770ad9 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 6 Sep 2023 21:25:50 +0800 Subject: [PATCH 060/103] Ondrej's comment on changing the raise exception to LoaderError --- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index d3b7c61ff8..d87d6b1bfe 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -1,10 +1,12 @@ import os from openpype.pipeline import load, get_representation_path +from openpype.pipeline.load import LoaderError from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, update_custom_attribute_data ) + from openpype.hosts.max.api.lib import ( unique_namespace, get_namespace, @@ -28,8 +30,8 @@ class OxAbcLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): plugin_list = get_plugins() if "ephere.plugins.autodesk.max.ornatrix.dlo" not in plugin_list: - raise RuntimeError("Ornatrix plugin not " - "found/installed in Max yet..") + raise LoaderError("Ornatrix plugin not " + "found/installed in Max yet..") file_path = os.path.normpath(self.filepath_from_context(context)) rt.AlembicImport.ImportToRoot = True From a0f7951ea3927de61722d299fb77239abfd9e033 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 16:02:46 +0200 Subject: [PATCH 061/103] Add job context parameter to USD publisher E.g. You can now directly export with a `Arnold` job context (if it's registered) so that the USD export is Arnold supported and directly renderable with shaders/render attributes by Arnold renderer. --- .../maya/plugins/create/create_maya_usd.py | 25 ++++++++++++++++++- .../maya/plugins/publish/extract_maya_usd.py | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/create/create_maya_usd.py b/openpype/hosts/maya/plugins/create/create_maya_usd.py index f05f155dd9..38de218bfb 100644 --- a/openpype/hosts/maya/plugins/create/create_maya_usd.py +++ b/openpype/hosts/maya/plugins/create/create_maya_usd.py @@ -5,6 +5,8 @@ from openpype.lib import ( TextDef ) +from maya import cmds + class CreateMayaUsd(plugin.MayaCreator): """Create Maya USD Export""" @@ -15,11 +17,28 @@ class CreateMayaUsd(plugin.MayaCreator): icon = "cubes" description = "Create Maya USD Export" + cache = {} + def get_publish_families(self): return ["usd", "mayaUsd"] def get_instance_attr_defs(self): + if "jobContextItems" not in self.cache: + # Query once instead of per instance + job_context_items = {} + try: + cmds.loadPlugin("mayaUsdPlugin", quiet=True) + job_context_items = { + cmds.mayaUSDListJobContexts(jobContext=name): name + for name in cmds.mayaUSDListJobContexts(export=True) + } + except RuntimeError: + # Likely `mayaUsdPlugin` plug-in not available + self.log.warning("Unable to retrieve available job " + "contexts for `mayaUsdPlugin` exports") + self.cache["jobContextItems"] = job_context_items + defs = lib.collect_animation_defs() defs.extend([ EnumDef("defaultUSDFormat", @@ -45,7 +64,11 @@ class CreateMayaUsd(plugin.MayaCreator): TextDef("attrPrefix", label="Custom Attributes Prefix", default="", - placeholder="prefix1, prefix2") + placeholder="prefix1, prefix2"), + EnumDef("jobContext", + label="Job Context", + items=self.cache["jobContextItems"], + multiselection=True), ]) return defs diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py index 09bbf01831..8c32ac1e39 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_usd.py @@ -148,6 +148,7 @@ class ExtractMayaUsd(publish.Extractor): "exportRefsAsInstanceable": bool, "eulerFilter": bool, "renderableOnly": bool, + "jobContext": (list, None) # optional list # "worldspace": bool, } @@ -169,6 +170,7 @@ class ExtractMayaUsd(publish.Extractor): "exportRefsAsInstanceable": False, "eulerFilter": True, "renderableOnly": False, + "jobContext": None # "worldspace": False } From 388ae935e1e37d5771816defd4983bb1d6092bd2 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 16:09:51 +0200 Subject: [PATCH 062/103] By default load proxy as *not* `Shareable` --- openpype/hosts/maya/plugins/load/load_maya_usd.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpype/hosts/maya/plugins/load/load_maya_usd.py b/openpype/hosts/maya/plugins/load/load_maya_usd.py index 26c497768d..2fb1a625a5 100644 --- a/openpype/hosts/maya/plugins/load/load_maya_usd.py +++ b/openpype/hosts/maya/plugins/load/load_maya_usd.py @@ -51,6 +51,14 @@ class MayaUsdLoader(load.LoaderPlugin): cmds.connectAttr("time1.outTime", "{}.time".format(proxy)) cmds.setAttr("{}.filePath".format(proxy), path, type="string") + # By default, we force the proxy to not use a shared stage because + # when doing so Maya will quite easily allow to save into the + # loaded usd file. Since we are loading published files we want to + # avoid altering them. Unshared stages also save their edits into + # the workfile as an artist might expect it to do. + cmds.setAttr("{}.shareStage".format(proxy), False) + # cmds.setAttr("{}.shareStage".format(proxy), lock=True) + nodes = [transform, proxy] self[:] = nodes From f1267546d23040eb778b9f8ead135d6de36184d9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 18:02:24 +0200 Subject: [PATCH 063/103] Avoid error if no job contexts are available --- openpype/hosts/maya/plugins/create/create_maya_usd.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/create/create_maya_usd.py b/openpype/hosts/maya/plugins/create/create_maya_usd.py index 38de218bfb..77a96dd4cb 100644 --- a/openpype/hosts/maya/plugins/create/create_maya_usd.py +++ b/openpype/hosts/maya/plugins/create/create_maya_usd.py @@ -31,12 +31,17 @@ class CreateMayaUsd(plugin.MayaCreator): cmds.loadPlugin("mayaUsdPlugin", quiet=True) job_context_items = { cmds.mayaUSDListJobContexts(jobContext=name): name - for name in cmds.mayaUSDListJobContexts(export=True) + for name in cmds.mayaUSDListJobContexts(export=True) or [] } except RuntimeError: # Likely `mayaUsdPlugin` plug-in not available self.log.warning("Unable to retrieve available job " "contexts for `mayaUsdPlugin` exports") + + if not job_context_items: + # enumdef multiselection may not be empty + job_context_items = [""] + self.cache["jobContextItems"] = job_context_items defs = lib.collect_animation_defs() From d5823ab556e016c424b7c4bdd12ddac646d745be Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 18:08:51 +0200 Subject: [PATCH 064/103] Add a few tooltips --- .../maya/plugins/create/create_maya_usd.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/openpype/hosts/maya/plugins/create/create_maya_usd.py b/openpype/hosts/maya/plugins/create/create_maya_usd.py index 77a96dd4cb..cc9a14bd3a 100644 --- a/openpype/hosts/maya/plugins/create/create_maya_usd.py +++ b/openpype/hosts/maya/plugins/create/create_maya_usd.py @@ -55,12 +55,29 @@ class CreateMayaUsd(plugin.MayaCreator): default="usdc"), BoolDef("stripNamespaces", label="Strip Namespaces", + tooltip=( + "Remove namespaces during export. By default, " + "namespaces are exported to the USD file in the " + "following format: nameSpaceExample_pPlatonic1" + ), default=True), BoolDef("mergeTransformAndShape", label="Merge Transform and Shape", + tooltip=( + "Combine Maya transform and shape into a single USD" + "prim that has transform and geometry, for all" + " \"geometric primitives\" (gprims).\n" + "This results in smaller and faster scenes. Gprims " + "will be \"unpacked\" back into transform and shape " + "nodes when imported into Maya from USD." + ), default=True), BoolDef("includeUserDefinedAttributes", label="Include User Defined Attributes", + tooltip=( + "Whether to include all custom maya attributes found " + "on nodes as metadata (userProperties) in USD." + ), default=False), TextDef("attr", label="Custom Attributes", @@ -73,6 +90,12 @@ class CreateMayaUsd(plugin.MayaCreator): EnumDef("jobContext", label="Job Context", items=self.cache["jobContextItems"], + tooltip=( + "Specifies an additional export context to handle.\n" + "These usually contain extra schemas, primitives,\n" + "and materials that are to be exported for a " + "specific\ntask, a target renderer for example." + ), multiselection=True), ]) From d2140c36192d353d68c287af6385fac1b8fa68d7 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 6 Sep 2023 21:37:20 +0300 Subject: [PATCH 065/103] match maya render mask in houdini --- openpype/hosts/houdini/api/lib.py | 53 ++++++++++++ openpype/hosts/houdini/api/pipeline.py | 2 + .../plugins/inventory/set_asset_resolution.py | 24 ++++++ .../hosts/houdini/plugins/load/load_camera.py | 81 +++++++++++-------- 4 files changed, 126 insertions(+), 34 deletions(-) create mode 100644 openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 75c7ff9fee..c6672cf969 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -649,3 +649,56 @@ def get_color_management_preferences(): "display": hou.Color.ocio_defaultDisplay(), "view": hou.Color.ocio_defaultView() } + + +def get_current_asset_doc(): + """Get asset document of the current asset. """ + + project_name = get_current_project_name() + asset_name = get_current_asset_name() + asset_doc = get_asset_by_name(project_name, asset_name) + + return asset_doc + + +def get_resolution_from_data(doc): + if not doc or "data" not in doc: + print("Entered document is not valid. \"{}\"".format(str(doc))) + return None + + resolution_width = doc["data"].get("resolutionWidth") + resolution_height = doc["data"].get("resolutionHeight") + + # Make sure both width and height are set + if resolution_width is None or resolution_height is None: + print("No resolution information found for \"{}\"".format(doc["name"])) + return None + + return int(resolution_width), int(resolution_height) + + +def set_camera_resolution(camera, asset_doc=None): + """Apply resolution to camera from asset document of the publish""" + + if not asset_doc: + asset_doc = get_current_asset_doc() + + resolution = get_resolution_from_data(asset_doc) + + if resolution: + print("Setting camera resolution: {} -> {}x{}".format( + camera.name(), resolution[0], resolution[1] + )) + camera.parm("resx").set(resolution[0]) + camera.parm("resy").set(resolution[1]) + + +def get_camera_from_container(container): + """Get camera from container node. """ + + cameras = container.recursiveGlob("*", + filter=hou.nodeTypeFilter.ObjCamera, + include_subnets=False) + + assert len(cameras) == 1, "Camera instance must have only one camera" + return cameras[0] diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index c9ae801af5..6aa65deb89 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -14,6 +14,7 @@ import pyblish.api from openpype.pipeline import ( register_creator_plugin_path, register_loader_plugin_path, + register_inventory_action_path, AVALON_CONTAINER_ID, ) from openpype.pipeline.load import any_outdated_containers @@ -55,6 +56,7 @@ class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost): pyblish.api.register_plugin_path(PUBLISH_PATH) register_loader_plugin_path(LOAD_PATH) register_creator_plugin_path(CREATE_PATH) + register_inventory_action_path(INVENTORY_PATH) log.info("Installing callbacks ... ") # register_event_callback("init", on_init) diff --git a/openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py b/openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py new file mode 100644 index 0000000000..cff7f89288 --- /dev/null +++ b/openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py @@ -0,0 +1,24 @@ +from openpype.pipeline import InventoryAction +from openpype.hosts.houdini.api.lib import ( + get_camera_from_container, + set_camera_resolution +) + +class SetAssetResolution(InventoryAction): + + label = "Set Asset Resolution" + icon = "desktop" + color = "orange" + + @staticmethod + def is_compatible(container): + print(container) + return ( + container.get("loader") == "CameraLoader" + ) + + def process(self, containers): + for container in containers: + node = container["node"] + camera = get_camera_from_container(node) + set_camera_resolution(camera) diff --git a/openpype/hosts/houdini/plugins/load/load_camera.py b/openpype/hosts/houdini/plugins/load/load_camera.py index 7b4a04809e..cffa5ca813 100644 --- a/openpype/hosts/houdini/plugins/load/load_camera.py +++ b/openpype/hosts/houdini/plugins/load/load_camera.py @@ -4,6 +4,13 @@ from openpype.pipeline import ( ) from openpype.hosts.houdini.api import pipeline +from openpype.hosts.houdini.api.lib import ( + set_camera_resolution, + get_camera_from_container +) + +import hou + ARCHIVE_EXPRESSION = ('__import__("_alembic_hom_extensions")' '.alembicGetCameraDict') @@ -25,7 +32,15 @@ def transfer_non_default_values(src, dest, ignore=None): channel expression and ignore certain Parm types. """ - import hou + + ignore_types = { + hou.parmTemplateType.Toggle, + hou.parmTemplateType.Menu, + hou.parmTemplateType.Button, + hou.parmTemplateType.FolderSet, + hou.parmTemplateType.Separator, + hou.parmTemplateType.Label, + } src.updateParmStates() @@ -62,14 +77,6 @@ def transfer_non_default_values(src, dest, ignore=None): continue # Ignore folders, separators, etc. - ignore_types = { - hou.parmTemplateType.Toggle, - hou.parmTemplateType.Menu, - hou.parmTemplateType.Button, - hou.parmTemplateType.FolderSet, - hou.parmTemplateType.Separator, - hou.parmTemplateType.Label, - } if parm.parmTemplate().type() in ignore_types: continue @@ -90,13 +97,8 @@ class CameraLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): - import os - import hou - # Format file name, Houdini only wants forward slashes - file_path = self.filepath_from_context(context) - file_path = os.path.normpath(file_path) - file_path = file_path.replace("\\", "/") + file_path = self.fname.replace("\\", "/") # Get the root node obj = hou.node("/obj") @@ -106,19 +108,21 @@ class CameraLoader(load.LoaderPlugin): node_name = "{}_{}".format(namespace, name) if namespace else name # Create a archive node - container = self.create_and_connect(obj, "alembicarchive", node_name) + node = self.create_and_connect(obj, "alembicarchive", node_name) # TODO: add FPS of project / asset - container.setParms({"fileName": file_path, - "channelRef": True}) + node.setParms({"fileName": file_path, "channelRef": True}) # Apply some magic - container.parm("buildHierarchy").pressButton() - container.moveToGoodPosition() + node.parm("buildHierarchy").pressButton() + node.moveToGoodPosition() # Create an alembic xform node - nodes = [container] + nodes = [node] + camera = get_camera_from_container(node) + self._match_maya_render_mask(camera) + set_camera_resolution(camera, asset_doc=context["asset"]) self[:] = nodes return pipeline.containerise(node_name, @@ -143,14 +147,14 @@ class CameraLoader(load.LoaderPlugin): # Store the cam temporarily next to the Alembic Archive # so that we can preserve parm values the user set on it # after build hierarchy was triggered. - old_camera = self._get_camera(node) + old_camera = get_camera_from_container(node) temp_camera = old_camera.copyTo(node.parent()) # Rebuild node.parm("buildHierarchy").pressButton() # Apply values to the new camera - new_camera = self._get_camera(node) + new_camera = get_camera_from_container(node) transfer_non_default_values(temp_camera, new_camera, # The hidden uniform scale attribute @@ -158,6 +162,9 @@ class CameraLoader(load.LoaderPlugin): # "icon_scale" just skip that completely ignore={"scale"}) + self._match_maya_render_mask(new_camera) + set_camera_resolution(new_camera) + temp_camera.destroy() def remove(self, container): @@ -165,15 +172,6 @@ class CameraLoader(load.LoaderPlugin): node = container["node"] node.destroy() - def _get_camera(self, node): - import hou - cameras = node.recursiveGlob("*", - filter=hou.nodeTypeFilter.ObjCamera, - include_subnets=False) - - assert len(cameras) == 1, "Camera instance must have only one camera" - return cameras[0] - def create_and_connect(self, node, node_type, name=None): """Create a node within a node which and connect it to the input @@ -194,5 +192,20 @@ class CameraLoader(load.LoaderPlugin): new_node.moveToGoodPosition() return new_node - def switch(self, container, representation): - self.update(container, representation) + def _match_maya_render_mask(self, camera): + """Workaround to match Maya render mask in Houdini""" + + # print("Setting match maya render mask ") + parm = camera.parm("aperture") + expression = parm.expression() + expression = expression.replace("return ", "aperture = ") + expression += """ +# Match maya render mask (logic from Houdini's own FBX importer) +node = hou.pwd() +resx = node.evalParm('resx') +resy = node.evalParm('resy') +aspect = node.evalParm('aspect') +aperture *= min(1, (resx / resy * aspect) / 1.5) +return aperture +""" + parm.setExpression(expression, language=hou.exprLanguage.Python) From 32a192b1929598c82fc8d199b19ff0edb5763564 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 6 Sep 2023 21:44:46 +0300 Subject: [PATCH 066/103] change action name --- .../{set_asset_resolution.py => set_camera_resolution.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename openpype/hosts/houdini/plugins/inventory/{set_asset_resolution.py => set_camera_resolution.py} (87%) diff --git a/openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py similarity index 87% rename from openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py rename to openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py index cff7f89288..441aef8b1c 100644 --- a/openpype/hosts/houdini/plugins/inventory/set_asset_resolution.py +++ b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py @@ -4,9 +4,9 @@ from openpype.hosts.houdini.api.lib import ( set_camera_resolution ) -class SetAssetResolution(InventoryAction): +class SetCameraResolution(InventoryAction): - label = "Set Asset Resolution" + label = "Set Camera Resolution" icon = "desktop" color = "orange" From f8d03955f71b6d7fe9d87b1835cb1d62a2adf788 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Wed, 6 Sep 2023 21:59:11 +0300 Subject: [PATCH 067/103] resolve hound --- openpype/hosts/houdini/api/lib.py | 14 +++++++++----- .../plugins/inventory/set_camera_resolution.py | 1 + openpype/hosts/houdini/plugins/load/load_camera.py | 14 +++++++------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index c6672cf969..f83519ddb8 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -661,7 +661,9 @@ def get_current_asset_doc(): return asset_doc -def get_resolution_from_data(doc): +def get_resolution_from_doc(doc): + """Get resolution from the given asset document. """ + if not doc or "data" not in doc: print("Entered document is not valid. \"{}\"".format(str(doc))) return None @@ -683,7 +685,7 @@ def set_camera_resolution(camera, asset_doc=None): if not asset_doc: asset_doc = get_current_asset_doc() - resolution = get_resolution_from_data(asset_doc) + resolution = get_resolution_from_doc(asset_doc) if resolution: print("Setting camera resolution: {} -> {}x{}".format( @@ -696,9 +698,11 @@ def set_camera_resolution(camera, asset_doc=None): def get_camera_from_container(container): """Get camera from container node. """ - cameras = container.recursiveGlob("*", - filter=hou.nodeTypeFilter.ObjCamera, - include_subnets=False) + cameras = container.recursiveGlob( + "*", + filter=hou.nodeTypeFilter.ObjCamera, + include_subnets=False + ) assert len(cameras) == 1, "Camera instance must have only one camera" return cameras[0] diff --git a/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py index 441aef8b1c..5dd94232b8 100644 --- a/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py +++ b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py @@ -4,6 +4,7 @@ from openpype.hosts.houdini.api.lib import ( set_camera_resolution ) + class SetCameraResolution(InventoryAction): label = "Set Camera Resolution" diff --git a/openpype/hosts/houdini/plugins/load/load_camera.py b/openpype/hosts/houdini/plugins/load/load_camera.py index cffa5ca813..53567b6f97 100644 --- a/openpype/hosts/houdini/plugins/load/load_camera.py +++ b/openpype/hosts/houdini/plugins/load/load_camera.py @@ -34,13 +34,13 @@ def transfer_non_default_values(src, dest, ignore=None): """ ignore_types = { - hou.parmTemplateType.Toggle, - hou.parmTemplateType.Menu, - hou.parmTemplateType.Button, - hou.parmTemplateType.FolderSet, - hou.parmTemplateType.Separator, - hou.parmTemplateType.Label, - } + hou.parmTemplateType.Toggle, + hou.parmTemplateType.Menu, + hou.parmTemplateType.Button, + hou.parmTemplateType.FolderSet, + hou.parmTemplateType.Separator, + hou.parmTemplateType.Label, + } src.updateParmStates() From 7a3aaa5408b3d4a9ff22220018506e25e55858bf Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 7 Sep 2023 10:26:09 +0300 Subject: [PATCH 068/103] replace fname --- openpype/hosts/houdini/plugins/load/load_camera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/load/load_camera.py b/openpype/hosts/houdini/plugins/load/load_camera.py index 53567b6f97..e16146a267 100644 --- a/openpype/hosts/houdini/plugins/load/load_camera.py +++ b/openpype/hosts/houdini/plugins/load/load_camera.py @@ -98,7 +98,7 @@ class CameraLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): # Format file name, Houdini only wants forward slashes - file_path = self.fname.replace("\\", "/") + file_path = self.filepath_from_context(context).replace("\\", "/") # Get the root node obj = hou.node("/obj") From 9d2fc2fca4622e8c91ba4539034a03f67b57fc40 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 7 Sep 2023 22:30:03 +0300 Subject: [PATCH 069/103] Jakub comments --- openpype/hosts/houdini/api/lib.py | 12 +----------- .../plugins/inventory/set_camera_resolution.py | 6 +++--- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index f83519ddb8..eff98c05f1 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -651,16 +651,6 @@ def get_color_management_preferences(): } -def get_current_asset_doc(): - """Get asset document of the current asset. """ - - project_name = get_current_project_name() - asset_name = get_current_asset_name() - asset_doc = get_asset_by_name(project_name, asset_name) - - return asset_doc - - def get_resolution_from_doc(doc): """Get resolution from the given asset document. """ @@ -683,7 +673,7 @@ def set_camera_resolution(camera, asset_doc=None): """Apply resolution to camera from asset document of the publish""" if not asset_doc: - asset_doc = get_current_asset_doc() + asset_doc = get_current_project_asset() resolution = get_resolution_from_doc(asset_doc) diff --git a/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py index 5dd94232b8..97b94e66aa 100644 --- a/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py +++ b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py @@ -3,7 +3,7 @@ from openpype.hosts.houdini.api.lib import ( get_camera_from_container, set_camera_resolution ) - +from openpype.pipeline.context_tools import get_current_project_asset class SetCameraResolution(InventoryAction): @@ -13,13 +13,13 @@ class SetCameraResolution(InventoryAction): @staticmethod def is_compatible(container): - print(container) return ( container.get("loader") == "CameraLoader" ) def process(self, containers): + asset_doc = get_current_project_asset() for container in containers: node = container["node"] camera = get_camera_from_container(node) - set_camera_resolution(camera) + set_camera_resolution(camera, asset_doc) From d38d25308dc393ced6504e86e925d8c821c92868 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 7 Sep 2023 22:31:48 +0300 Subject: [PATCH 070/103] resolve hound --- .../hosts/houdini/plugins/inventory/set_camera_resolution.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py index 97b94e66aa..18ececb019 100644 --- a/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py +++ b/openpype/hosts/houdini/plugins/inventory/set_camera_resolution.py @@ -5,6 +5,7 @@ from openpype.hosts.houdini.api.lib import ( ) from openpype.pipeline.context_tools import get_current_project_asset + class SetCameraResolution(InventoryAction): label = "Set Camera Resolution" From 1365bec5188cfb810ee73b442e9393bf918c2ab9 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 11 Sep 2023 16:19:15 +0200 Subject: [PATCH 071/103] :recycle: add check for produced file --- openpype/hosts/max/plugins/publish/extract_model_obj.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/extract_model_obj.py b/openpype/hosts/max/plugins/publish/extract_model_obj.py index e522b1e7a1..a5d9ad6597 100644 --- a/openpype/hosts/max/plugins/publish/extract_model_obj.py +++ b/openpype/hosts/max/plugins/publish/extract_model_obj.py @@ -3,6 +3,7 @@ import pyblish.api from openpype.pipeline import publish, OptionalPyblishPluginMixin from pymxs import runtime as rt from openpype.hosts.max.api import maintained_selection +from openpype.pipeline.publish import KnownPublishError class ExtractModelObj(publish.Extractor, OptionalPyblishPluginMixin): @@ -27,6 +28,7 @@ class ExtractModelObj(publish.Extractor, OptionalPyblishPluginMixin): filepath = os.path.join(stagingdir, filename) self.log.info("Writing OBJ '%s' to '%s'" % (filepath, stagingdir)) + self.log.info("Performing Extraction ...") with maintained_selection(): # select and export node_list = instance.data["members"] @@ -38,7 +40,10 @@ class ExtractModelObj(publish.Extractor, OptionalPyblishPluginMixin): using=rt.ObjExp, ) - self.log.info("Performing Extraction ...") + if not os.path.exists(filepath): + raise KnownPublishError( + "File {} wasn't produced by 3ds max, please check the logs.") + if "representations" not in instance.data: instance.data["representations"] = [] From 86629c85cab0cb59585f0fd0d6120a2c0c27f7fd Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 11 Sep 2023 16:21:35 +0200 Subject: [PATCH 072/103] :recycle: make usd plugin validator optional this is temporary hack to allow testing and publishing models without USD plugin in max as the plugin validator will run always, no matter if the USD extractor is enabled or not. This will change when #5602 is implemented. --- .../max/plugins/publish/validate_usd_plugin.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_usd_plugin.py b/openpype/hosts/max/plugins/publish/validate_usd_plugin.py index 9957e62736..36c4291925 100644 --- a/openpype/hosts/max/plugins/publish/validate_usd_plugin.py +++ b/openpype/hosts/max/plugins/publish/validate_usd_plugin.py @@ -1,9 +1,13 @@ # -*- coding: utf-8 -*- """Validator for USD plugin.""" -from openpype.pipeline import PublishValidationError from pyblish.api import InstancePlugin, ValidatorOrder from pymxs import runtime as rt +from openpype.pipeline import ( + OptionalPyblishPluginMixin, + PublishValidationError +) + def get_plugins() -> list: """Get plugin list from 3ds max.""" @@ -17,17 +21,25 @@ def get_plugins() -> list: return plugin_info_list -class ValidateUSDPlugin(InstancePlugin): +class ValidateUSDPlugin(OptionalPyblishPluginMixin, + InstancePlugin): """Validates if USD plugin is installed or loaded in 3ds max.""" order = ValidatorOrder - 0.01 families = ["model"] hosts = ["max"] - label = "USD Plugin" + label = "Validate USD Plugin loaded" + optional = True def process(self, instance): """Plugin entry point.""" + for sc in ValidateUSDPlugin.__subclasses__(): + self.log.info(sc) + + if not self.is_active(instance.data): + return + plugin_info = get_plugins() usd_import = "usdimport.dli" if usd_import not in plugin_info: From c292a11939a7cf3f980d018031e3da86335925c5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 13 Sep 2023 19:10:52 +0800 Subject: [PATCH 073/103] typo for LoadError --- openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index d87d6b1bfe..f8aadb53c0 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -1,6 +1,6 @@ import os from openpype.pipeline import load, get_representation_path -from openpype.pipeline.load import LoaderError +from openpype.pipeline.load import LoadError from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -30,8 +30,8 @@ class OxAbcLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): plugin_list = get_plugins() if "ephere.plugins.autodesk.max.ornatrix.dlo" not in plugin_list: - raise LoaderError("Ornatrix plugin not " - "found/installed in Max yet..") + raise LoadError("Ornatrix plugin not " + "found/installed in Max yet..") file_path = os.path.normpath(self.filepath_from_context(context)) rt.AlembicImport.ImportToRoot = True From 5f2756b95ee0d06b1ac2748b736db93dc47a7f46 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 13 Sep 2023 22:42:33 +0200 Subject: [PATCH 074/103] Skip view capture when Maya is in headless mode Co-authored-by: Toke Jepsen --- .../plugins/publish/extract_active_view_thumbnail.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py index b4e62f8acc..71a0ba877b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py @@ -4,6 +4,9 @@ import maya.api.OpenMayaUI as omui import pyblish.api import tempfile +from openpype.hosts.maya.lib import IS_HEADLESS + + class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): """Set instance thumbnail to a screengrab of current active viewport. @@ -19,6 +22,13 @@ class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): hosts = ["maya"] def process(self, instance): + if IS_HEADLESS: + self.log.debug( + "Skip extraction of active view thumbnail, due to being in" + "headless mode." + ) + return + thumbnail = instance.data.get("thumbnailPath") if not thumbnail: view_thumbnail = self.get_view_thumbnail(instance) From ef843e25ca35b2e0ab6b0be47f214093131e9c7c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 13 Sep 2023 23:01:58 +0200 Subject: [PATCH 075/103] Update openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py --- .../hosts/maya/plugins/publish/extract_active_view_thumbnail.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py index 71a0ba877b..f47dd5e084 100644 --- a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py @@ -7,7 +7,6 @@ import tempfile from openpype.hosts.maya.lib import IS_HEADLESS - class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): """Set instance thumbnail to a screengrab of current active viewport. From 5e20dd3f9cb553c053f35baf0fb321e6b46a3f43 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 14 Sep 2023 09:54:32 +0100 Subject: [PATCH 076/103] Update openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py --- .../hosts/maya/plugins/publish/extract_active_view_thumbnail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py index f47dd5e084..483ae6d9d3 100644 --- a/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_active_view_thumbnail.py @@ -4,7 +4,7 @@ import maya.api.OpenMayaUI as omui import pyblish.api import tempfile -from openpype.hosts.maya.lib import IS_HEADLESS +from openpype.hosts.maya.api.lib import IS_HEADLESS class ExtractActiveViewThumbnail(pyblish.api.InstancePlugin): From cdc6366662b00a3e0f413cdba8e1eb1784f10e28 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 14 Sep 2023 17:42:35 +0800 Subject: [PATCH 077/103] update the OP data after the merge of #5424 --- .../plugins/load/load_pointcache_ornatrix.py | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index f8aadb53c0..0f32b7938f 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -50,19 +50,13 @@ class OxAbcLoader(load.LoaderPlugin): name + "_", suffix="_", ) - - abc_container = rt.Container() + abc_container =[] for abc in scene_object: - abc.Parent = abc_container abc.name = f"{namespace}:{abc.name}" - # rename the abc container with namespace - abc_container_name = f"{namespace}:{name}_{self.postfix}" - abc_container.name = abc_container_name - import_custom_attribute_data( - abc_container, abc_container.Children) + abc_container.append(abc) return containerise( - name, [abc_container], context, + name, abc_container, context, namespace, loader=self.__class__.__name__ ) @@ -89,14 +83,17 @@ class OxAbcLoader(load.LoaderPlugin): obj_type = rt.ClassOf(obj) if str(obj_type).startswith("Ox_"): scene_object.append(obj) - update_custom_attribute_data( - inst_container, scene_object.Children) + ox_abc_objects = [] for abc in scene_object: abc.Parent = container abc.name = f"{namespace}:{abc.name}" - abc.pos = transform_data[f"{abc.name}.transform"] - abc.scale = transform_data[f"{abc.name}.scale"] - + ox_abc_objects.append(abc) + ox_transform = f"{abc.name}.transform" + if ox_transform in transform_data.keys(): + abc.pos = transform_data[ox_transform] or 0 + abc.scale = transform_data[f"{abc.name}.scale"] or 0 + update_custom_attribute_data( + inst_container, ox_abc_objects) lib.imprint( container["instance_node"], {"representation": str(representation["_id"])}, From 2bd4d295afda0e5f64434e6119d802180f4ca618 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 14 Sep 2023 17:46:32 +0800 Subject: [PATCH 078/103] update the Data & hound --- .../plugins/load/load_pointcache_ornatrix.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index 0f32b7938f..cbd15ae6b8 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -3,7 +3,7 @@ from openpype.pipeline import load, get_representation_path from openpype.pipeline.load import LoadError from openpype.hosts.max.api.pipeline import ( containerise, - import_custom_attribute_data, + get_previous_loaded_object, update_custom_attribute_data ) @@ -50,7 +50,7 @@ class OxAbcLoader(load.LoaderPlugin): name + "_", suffix="_", ) - abc_container =[] + abc_container = [] for abc in scene_object: abc.name = f"{namespace}:{abc.name}" abc_container.append(abc) @@ -64,11 +64,12 @@ class OxAbcLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] namespace, name = get_namespace(node_name) - sub_node_name = f"{namespace}:{name}_{self.postfix}" - inst_container = rt.getNodeByName(sub_node_name) - rt.Select(inst_container.Children) - transform_data = object_transform_set(inst_container.Children) - for prev_obj in rt.selection: + node = rt.getNodeByName(node_name) + node_list = get_previous_loaded_object(node) + rt.Select(node_list) + selections = rt.getCurrentSelection() + transform_data = object_transform_set(selections) + for prev_obj in selections: if rt.isValidNode(prev_obj): rt.Delete(prev_obj) @@ -92,8 +93,7 @@ class OxAbcLoader(load.LoaderPlugin): if ox_transform in transform_data.keys(): abc.pos = transform_data[ox_transform] or 0 abc.scale = transform_data[f"{abc.name}.scale"] or 0 - update_custom_attribute_data( - inst_container, ox_abc_objects) + update_custom_attribute_data(node, ox_abc_objects) lib.imprint( container["instance_node"], {"representation": str(representation["_id"])}, From 963f3f42ff287742e6aa2004292dc513464bcaa8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 14 Sep 2023 17:48:18 +0800 Subject: [PATCH 079/103] use the get_plugins function from max.api.lib --- .../max/plugins/load/load_pointcache_ornatrix.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py index cbd15ae6b8..96060a6a6f 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py +++ b/openpype/hosts/max/plugins/load/load_pointcache_ornatrix.py @@ -10,7 +10,8 @@ from openpype.hosts.max.api.pipeline import ( from openpype.hosts.max.api.lib import ( unique_namespace, get_namespace, - object_transform_set + object_transform_set, + get_plugins ) from openpype.hosts.max.api import lib from pymxs import runtime as rt @@ -105,15 +106,3 @@ class OxAbcLoader(load.LoaderPlugin): def remove(self, container): node = rt.GetNodeByName(container["instance_node"]) rt.Delete(node) - - -def get_plugins() -> list: - """Get plugin list from 3ds max.""" - manager = rt.PluginManager - count = manager.pluginDllCount - plugin_info_list = [] - for p in range(1, count + 1): - plugin_info = manager.pluginDllName(p) - plugin_info_list.append(plugin_info) - - return plugin_info_list From 254a1859632b9b5ce59fb58c8cdb47a754ae746d Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 14 Sep 2023 22:35:04 +0300 Subject: [PATCH 080/103] set PATH environment in deadline jobs --- .../repository/custom/plugins/GlobalJobPreLoad.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index 97875215ae..79cd3968fb 100644 --- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -385,6 +385,11 @@ def inject_openpype_environment(deadlinePlugin): for key, value in contents.items(): deadlinePlugin.SetProcessEnvironmentVariable(key, value) + if "PATH" in contents: + PATH = contents["PATH"] + print(f">>> Set 'PATH' Environment to: {PATH}") + os.environ["PATH"] = PATH + script_url = job.GetJobPluginInfoKeyValue("ScriptFilename") if script_url: script_url = script_url.format(**contents).replace("\\", "/") @@ -509,6 +514,11 @@ def inject_ayon_environment(deadlinePlugin): for key, value in contents.items(): deadlinePlugin.SetProcessEnvironmentVariable(key, value) + if "PATH" in contents: + PATH = contents["PATH"] + print(f">>> Set 'PATH' Environment to: {PATH}") + os.environ["PATH"] = PATH + script_url = job.GetJobPluginInfoKeyValue("ScriptFilename") if script_url: script_url = script_url.format(**contents).replace("\\", "/") From f7cc7f1908948fc0aa1526987b8cc12a20dd4736 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 14 Sep 2023 23:17:52 +0300 Subject: [PATCH 081/103] BigRoy's comment --- .../deadline/repository/custom/plugins/GlobalJobPreLoad.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index 79cd3968fb..24bfd983f3 100644 --- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -387,7 +387,7 @@ def inject_openpype_environment(deadlinePlugin): if "PATH" in contents: PATH = contents["PATH"] - print(f">>> Set 'PATH' Environment to: {PATH}") + print(f">>> Setting 'PATH' Environment to: {PATH}") os.environ["PATH"] = PATH script_url = job.GetJobPluginInfoKeyValue("ScriptFilename") @@ -516,7 +516,7 @@ def inject_ayon_environment(deadlinePlugin): if "PATH" in contents: PATH = contents["PATH"] - print(f">>> Set 'PATH' Environment to: {PATH}") + print(f">>> Setting 'PATH' Environment to: {PATH}") os.environ["PATH"] = PATH script_url = job.GetJobPluginInfoKeyValue("ScriptFilename") From 1ec11da6f7c25550edd030461845b88681c1b4a6 Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Thu, 14 Sep 2023 23:23:31 +0300 Subject: [PATCH 082/103] add a developer note --- .../deadline/repository/custom/plugins/GlobalJobPreLoad.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index 24bfd983f3..044a953083 100644 --- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -386,6 +386,8 @@ def inject_openpype_environment(deadlinePlugin): deadlinePlugin.SetProcessEnvironmentVariable(key, value) if "PATH" in contents: + # Set os.environ[PATH] so studio settings' path entries + # can be used to define search path for executables. PATH = contents["PATH"] print(f">>> Setting 'PATH' Environment to: {PATH}") os.environ["PATH"] = PATH @@ -515,6 +517,8 @@ def inject_ayon_environment(deadlinePlugin): deadlinePlugin.SetProcessEnvironmentVariable(key, value) if "PATH" in contents: + # Set os.environ[PATH] so studio settings' path entries + # can be used to define search path for executables. PATH = contents["PATH"] print(f">>> Setting 'PATH' Environment to: {PATH}") os.environ["PATH"] = PATH From 0c09a6772ce3c0f3c9ce47547e937e9dc254d6fe Mon Sep 17 00:00:00 2001 From: Mustafa-Zarkash Date: Fri, 15 Sep 2023 09:50:13 +0300 Subject: [PATCH 083/103] BigRoy's comment --- .../repository/custom/plugins/GlobalJobPreLoad.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py index 044a953083..e9b81369ca 100644 --- a/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py +++ b/openpype/modules/deadline/repository/custom/plugins/GlobalJobPreLoad.py @@ -388,9 +388,8 @@ def inject_openpype_environment(deadlinePlugin): if "PATH" in contents: # Set os.environ[PATH] so studio settings' path entries # can be used to define search path for executables. - PATH = contents["PATH"] - print(f">>> Setting 'PATH' Environment to: {PATH}") - os.environ["PATH"] = PATH + print(f">>> Setting 'PATH' Environment to: {contents['PATH']}") + os.environ["PATH"] = contents["PATH"] script_url = job.GetJobPluginInfoKeyValue("ScriptFilename") if script_url: @@ -519,9 +518,8 @@ def inject_ayon_environment(deadlinePlugin): if "PATH" in contents: # Set os.environ[PATH] so studio settings' path entries # can be used to define search path for executables. - PATH = contents["PATH"] - print(f">>> Setting 'PATH' Environment to: {PATH}") - os.environ["PATH"] = PATH + print(f">>> Setting 'PATH' Environment to: {contents['PATH']}") + os.environ["PATH"] = contents["PATH"] script_url = job.GetJobPluginInfoKeyValue("ScriptFilename") if script_url: From 9f040265e7cd965df20137d9da12396fa8338310 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 18 Sep 2023 16:07:54 +0100 Subject: [PATCH 084/103] Remove context prompt. --- openpype/hosts/maya/api/pipeline.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/openpype/hosts/maya/api/pipeline.py b/openpype/hosts/maya/api/pipeline.py index 60495ac652..3647ec0b6b 100644 --- a/openpype/hosts/maya/api/pipeline.py +++ b/openpype/hosts/maya/api/pipeline.py @@ -659,17 +659,6 @@ def on_task_changed(): lib.set_context_settings() lib.update_content_on_context_change() - msg = " project: {}\n asset: {}\n task:{}".format( - get_current_project_name(), - get_current_asset_name(), - get_current_task_name() - ) - - lib.show_message( - "Context was changed", - ("Context was changed to:\n{}".format(msg)), - ) - def before_workfile_open(): if handle_workfile_locks(): From b8997c5ae49841ed3dfc82c30d394909a3b88722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:23:45 +0200 Subject: [PATCH 085/103] create symlinks for ssl libs (#5633) build was missing `libssl.1.1.so` and `libcrypto.1.1.so` symlinks needed by the executable itself, because python is now explicitly build with OpenSSL 1.1.1 --- Dockerfile.centos7 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile.centos7 b/Dockerfile.centos7 index 9217140f20..ab1d3f8253 100644 --- a/Dockerfile.centos7 +++ b/Dockerfile.centos7 @@ -109,6 +109,8 @@ RUN source $HOME/.bashrc \ RUN cp /usr/lib64/libffi* ./build/exe.linux-x86_64-3.9/lib \ && cp /usr/lib64/openssl11/libssl* ./build/exe.linux-x86_64-3.9/lib \ && cp /usr/lib64/openssl11/libcrypto* ./build/exe.linux-x86_64-3.9/lib \ + && ln -sr ./build/exe.linux-x86_64-3.9/lib/libssl.so ./build/exe.linux-x86_64-3.9/lib/libssl.1.1.so \ + && ln -sr ./build/exe.linux-x86_64-3.9/lib/libcrypto.so ./build/exe.linux-x86_64-3.9/lib/libcrypto.1.1.so \ && cp /root/.pyenv/versions/${OPENPYPE_PYTHON_VERSION}/lib/libpython* ./build/exe.linux-x86_64-3.9/lib \ && cp /usr/lib64/libxcb* ./build/exe.linux-x86_64-3.9/vendor/python/PySide2/Qt/lib From a8fa44c3fda18d0799fc171cb6461ba80672a36d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:52:51 +0200 Subject: [PATCH 086/103] AYON: Ignore separated modules (#5619) * ayon mode explicitly ignores addons that have own repository * change warning message of missing addon directory to debug * Better log message --- openpype/modules/base.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/openpype/modules/base.py b/openpype/modules/base.py index 84e213288c..a3c21718b9 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -59,6 +59,14 @@ IGNORED_DEFAULT_FILENAMES = ( "example_addons", "default_modules", ) +# Modules that won't be loaded in AYON mode from "./openpype/modules" +# - the same modules are ignored in "./server_addon/create_ayon_addons.py" +IGNORED_FILENAMES_IN_AYON = { + "ftrack", + "shotgrid", + "sync_server", + "slack", +} # Inherit from `object` for Python 2 hosts @@ -392,9 +400,9 @@ def _load_ayon_addons(openpype_modules, modules_key, log): folder_name = "{}_{}".format(addon_name, addon_version) addon_dir = os.path.join(addons_dir, folder_name) if not os.path.exists(addon_dir): - log.warning(( - "Directory for addon {} {} does not exists. Path \"{}\"" - ).format(addon_name, addon_version, addon_dir)) + log.debug(( + "No localized client code found for addon {} {}." + ).format(addon_name, addon_version)) continue sys.path.insert(0, addon_dir) @@ -483,6 +491,10 @@ def _load_modules(): is_in_current_dir = dirpath == current_dir is_in_host_dir = dirpath == hosts_dir + ignored_current_dir_filenames = set(IGNORED_DEFAULT_FILENAMES) + if AYON_SERVER_ENABLED: + ignored_current_dir_filenames |= IGNORED_FILENAMES_IN_AYON + for filename in os.listdir(dirpath): # Ignore filenames if filename in IGNORED_FILENAMES: @@ -490,7 +502,7 @@ def _load_modules(): if ( is_in_current_dir - and filename in IGNORED_DEFAULT_FILENAMES + and filename in ignored_current_dir_filenames ): continue From bed1e35d20dfc949a8b8c3864bbb526644fa37df Mon Sep 17 00:00:00 2001 From: 64qam Date: Tue, 19 Sep 2023 16:54:48 +0200 Subject: [PATCH 087/103] Default create a desktop icon is checked (#5636) --- inno_setup.iss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/inno_setup.iss b/inno_setup.iss index 418bedbd4d..d9a41d22ee 100644 --- a/inno_setup.iss +++ b/inno_setup.iss @@ -36,7 +36,7 @@ WizardStyle=modern Name: "english"; MessagesFile: "compiler:Default.isl" [Tasks] -Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" [InstallDelete] ; clean everything in previous installation folder @@ -53,4 +53,3 @@ Name: "{autodesktop}\{#MyAppName} {#AppVer}"; Filename: "{app}\openpype_gui.exe" [Run] Filename: "{app}\openpype_gui.exe"; Description: "{cm:LaunchProgram,OpenPype}"; Flags: nowait postinstall skipifsilent - From 50af3321ae9a9e0118f6b25eb7845ce6f9ab1762 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 19 Sep 2023 17:18:46 +0200 Subject: [PATCH 088/103] AYON: Avoid creation of duplicated links (#5593) * create set of output links before creation * find all existing links before creating them * Added small comment --- .../publish/integrate_inputlinks_ayon.py | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/openpype/plugins/publish/integrate_inputlinks_ayon.py b/openpype/plugins/publish/integrate_inputlinks_ayon.py index 180524cd08..28684aa889 100644 --- a/openpype/plugins/publish/integrate_inputlinks_ayon.py +++ b/openpype/plugins/publish/integrate_inputlinks_ayon.py @@ -1,7 +1,11 @@ import collections import pyblish.api -from ayon_api import create_link, make_sure_link_type_exists +from ayon_api import ( + create_link, + make_sure_link_type_exists, + get_versions_links, +) from openpype import AYON_SERVER_ENABLED @@ -124,6 +128,33 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin): version_entity["_id"], ) + def _get_existing_links(self, project_name, link_type, entity_ids): + """Find all existing links for given version ids. + + Args: + project_name (str): Name of project. + link_type (str): Type of link. + entity_ids (set[str]): Set of version ids. + + Returns: + dict[str, set[str]]: Existing links by version id. + """ + + output = collections.defaultdict(set) + if not entity_ids: + return output + + existing_in_links = get_versions_links( + project_name, entity_ids, [link_type], "output" + ) + + for entity_id, links in existing_in_links.items(): + if not links: + continue + for link in links: + output[entity_id].add(link["entityId"]) + return output + def create_links_on_server(self, context, new_links): """Create new links on server. @@ -144,16 +175,32 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin): # Create link themselves for link_type, items in new_links.items(): + mapping = collections.defaultdict(set) + # Make sure there are no duplicates of src > dst ids for item in items: - input_id, output_id = item - create_link( - project_name, - link_type, - input_id, - "version", - output_id, - "version" - ) + _input_id, _output_id = item + mapping[_input_id].add(_output_id) + + existing_links_by_in_id = self._get_existing_links( + project_name, link_type, set(mapping.keys()) + ) + + for input_id, output_ids in mapping.items(): + existing_links = existing_links_by_in_id[input_id] + for output_id in output_ids: + # Skip creation of link if already exists + # NOTE: AYON server does not support + # to have same links + if output_id in existing_links: + continue + create_link( + project_name, + link_type, + input_id, + "version", + output_id, + "version" + ) if not AYON_SERVER_ENABLED: From 85951d58f64920b33e9c6902569d890dcc1690f2 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Tue, 19 Sep 2023 15:31:39 +0000 Subject: [PATCH 089/103] [Automated] Release --- CHANGELOG.md | 251 ++++++++++++++++++++++++++++++++++++++++++++ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 253 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d7620869b..935e7dbc4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,257 @@ # Changelog +## [3.16.7](https://github.com/ynput/OpenPype/tree/3.16.7) + + +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.16.6...3.16.7) + +### **🆕 New features** + + +
+Maya: Extract active view as thumbnail when no thumbnail set #5426 + +This sets the Maya instance's thumbnail to the current active view if no thumbnail was set yet. + + +___ + +
+ + +
+Maya: Implement USD publish and load using native `mayaUsdPlugin` #5573 + +Implement Creator and Loaders for extraction and loading of USD files using Maya's own `mayaUsdPlugin`.Also adds support to load a `usd` file into an Arnold Standin (`aiStandin`) and assigning looks to it. + + +___ + +
+ + +
+AYON: Ignore separated modules #5619 + +Do not load already separated modules from default directory. + + +___ + +
+ +### **🚀 Enhancements** + + +
+Maya: Reduce amount of code for Collect Looks #5253 + +- Refactor `get_file_node_files` because popping from `paths` by index should have been done in reversed order anyway. It's now changed to not need popping at all. +- Removed unused `RENDERER_NODE_TYPES` and if-branch which collected `node_attrs` list which was unused + collected members which was also done outside of the if branch and thus generated no extra data. +- Collected all materials from look set attributes at once instead of multiple queries +- Collected all file nodes in history from a single query instead of per type +- Restructured assignment of `instance.data["resources"]` to be more readable +- Cached `PXR_NODES` only ones (Note: plugin load is checked on discovery of the collect look plugin) instead of querying plugin load and its nodes per file node per attribute +- Removed some debug logs or combined some messages + + +___ + +
+ + +
+AYON: Mark deprecated settings in Maya #5627 + +Added deprecated info to docstrings of maya colormanagement settings.Resolves: https://github.com/ynput/OpenPype/issues/5556 + + +___ + +
+ + +
+Max: switching versions of maxScene maintain parentage/links with the loaders #5424 + +When using scene inventory to manage or update the version of the loading objects, the linked modifiers or parentage of the objects would be kept.Meanwhile, loaded objects from all loaders no longer parented to the container with OP Data. + + +___ + +
+ + +
+3ds max: small tweaks to obj extractor and model publishing flow #5605 + +There migh be situation where OBJ Extractor passes without failure, but no obj file is produced. This is adding simple check directly into the extractor to catch it earlier then in the integration phase. Also switched `Validate USD Plugin` to optional, because it was always run no matter if the Extract USD was enabled or not, hindering testing (and publishing). + + +___ + +
+ + +
+TVPaint: Plugin can be reopened #5610 + +TVPaint plugin can be reopened. + + +___ + +
+ + +
+Maya: Remove context prompt #5632 + +More of a plea than a PR, but could we please remove the context prompt in Maya when switching tasks? + + +___ + +
+ + +
+General: Create a desktop icon is checked #5636 + +In OP Installer `Create a desktop icon` is checked by default. +___ + +
+ +### **🐛 Bug fixes** + + +
+Maya: Extract look is not AYON compatible - OP-5375 #5341 + +The textures that would use hardlinking are going through texture processors. Currently all texture processors are hardcoded to copy texture instead of respecting the settings of forcing to copy.The texture processors were last modified 4 months ago, so effectively all clients that are on any pipeline updated in the last 4 months wont be utilizing hardlinking at all, since the hardcoded texture processors will copy texture no matter the OS.This opts for completely disabling the hardlinking feature, while we figure out what to do about it. + + +___ + +
+ + +
+Maya: Multiverse USD Override inherit from correct new style creator #5566 + +Fix Creator for Multiverse USD Override by inheriting from correct new style creator class type + + +___ + +
+ + +
+Max: Bug Fix Alembic Loaders with Ornatrix #5434 + +Bugfix the alembic loader with both ornatrix alembic and max alembic supportsAdd the ornatrix alembic loaders for loading the alembic with Ornatrix-related modifiers. + + +___ + +
+ + +
+AYON: Avoid creation of duplicated links #5593 + +Handle cases when an existing link should be recreated and do not create the same link multitple times during single publishing. + + +___ + +
+ + +
+Extract Review: Multilayer specification for ffmpeg #5613 + +Extract review is specifying layer name when exr is multilayer. + + +___ + +
+ + +
+Fussion: added support for Fusion 17 #5614 + +Fusion 17 still uses Python 3.6 which causes issues with some our delivered libraries. Vendorized necessary set for Python 3.6 + + +___ + +
+ + +
+Publisher: Fix screenshot widget #5615 + +Use correct super method name.EDITED:Removed fade animation which is not triggered at some cases, e.g. in Nuke the animation does not start. I do expect that is caused by `exec_` on the dialog, which blocks event processing to the animation, even when I've added the window as parent it still didn't trigger registered callback.Modified how the "empty" space is not filled by using paths instead of clear mode on painter. Added render hints to add antialiasing. + + +___ + +
+ + +
+Photoshop: auto_images without alpha will not fail #5620 + +ExtractReview caused issue on `auto_image` instance without alpha channel, this fixes it. + + +___ + +
+ + +
+Fix - _id key used instead of id in get_last_version_by_subset_name #5626 + +Just 'id' is not returned because value in fields. Caused KeyError. + + +___ + +
+ + +
+Bugfix: create symlinks for ssl libs on Centos 7 #5633 + +Docker build was missing `libssl.1.1.so` and `libcrypto.1.1.so` symlinks needed by the executable itself, because Python is now explicitly built with OpenSSL 1.1.1 + + +___ + +
+ +### **📃 Documentation** + + +
+Documentation/local settings #5102 + +I completed the "Working with local settings" page. I updated the screenshot, wrote an explanation for each empty category, and if available, linked the more detailed pages already existing. I also added the "Environments" category. + + +___ + +
+ + + + ## [3.16.6](https://github.com/ynput/OpenPype/tree/3.16.6) diff --git a/openpype/version.py b/openpype/version.py index bbed1b0ef3..c593f0f71f 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.16.7-nightly.2" +__version__ = "3.16.7" diff --git a/pyproject.toml b/pyproject.toml index f859e1aff4..b394a895e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.16.6" # OpenPype +version = "3.16.7" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 16641e750045f8639a7138b83580ba089abfc492 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 Sep 2023 15:32:44 +0000 Subject: [PATCH 090/103] 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 cf3cb8ba1a..9159d3fe4a 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.16.7 - 3.16.7-nightly.2 - 3.16.7-nightly.1 - 3.16.6 @@ -134,7 +135,6 @@ body: - 3.14.10-nightly.2 - 3.14.10-nightly.1 - 3.14.9 - - 3.14.9-nightly.5 validations: required: true - type: dropdown From 982c72224cdbf3b92ac954d42e03769a79bbd6f4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:21:05 +0200 Subject: [PATCH 091/103] Chore: Remove schema from OpenPype root (#5355) * removed schema from openpype root * removed schema from include files --- schema/application-1.0.json | 68 ---------------- schema/asset-1.0.json | 35 -------- schema/asset-2.0.json | 55 ------------- schema/asset-3.0.json | 55 ------------- schema/config-1.0.json | 85 -------------------- schema/config-1.1.json | 87 -------------------- schema/config-2.0.json | 87 -------------------- schema/container-1.0.json | 100 ----------------------- schema/container-2.0.json | 59 -------------- schema/hero_version-1.0.json | 44 ---------- schema/inventory-1.0.json | 10 --- schema/inventory-1.1.json | 10 --- schema/project-2.0.json | 86 -------------------- schema/project-2.1.json | 86 -------------------- schema/project-3.0.json | 59 -------------- schema/representation-1.0.json | 28 ------- schema/representation-2.0.json | 78 ------------------ schema/session-1.0.json | 143 --------------------------------- schema/session-2.0.json | 134 ------------------------------ schema/session-3.0.json | 81 ------------------- schema/shaders-1.0.json | 32 -------- schema/subset-1.0.json | 35 -------- schema/subset-2.0.json | 51 ------------ schema/subset-3.0.json | 62 -------------- schema/thumbnail-1.0.json | 42 ---------- schema/version-1.0.json | 50 ------------ schema/version-2.0.json | 92 --------------------- schema/version-3.0.json | 84 ------------------- schema/workfile-1.0.json | 52 ------------ setup.py | 1 - 30 files changed, 1891 deletions(-) delete mode 100644 schema/application-1.0.json delete mode 100644 schema/asset-1.0.json delete mode 100644 schema/asset-2.0.json delete mode 100644 schema/asset-3.0.json delete mode 100644 schema/config-1.0.json delete mode 100644 schema/config-1.1.json delete mode 100644 schema/config-2.0.json delete mode 100644 schema/container-1.0.json delete mode 100644 schema/container-2.0.json delete mode 100644 schema/hero_version-1.0.json delete mode 100644 schema/inventory-1.0.json delete mode 100644 schema/inventory-1.1.json delete mode 100644 schema/project-2.0.json delete mode 100644 schema/project-2.1.json delete mode 100644 schema/project-3.0.json delete mode 100644 schema/representation-1.0.json delete mode 100644 schema/representation-2.0.json delete mode 100644 schema/session-1.0.json delete mode 100644 schema/session-2.0.json delete mode 100644 schema/session-3.0.json delete mode 100644 schema/shaders-1.0.json delete mode 100644 schema/subset-1.0.json delete mode 100644 schema/subset-2.0.json delete mode 100644 schema/subset-3.0.json delete mode 100644 schema/thumbnail-1.0.json delete mode 100644 schema/version-1.0.json delete mode 100644 schema/version-2.0.json delete mode 100644 schema/version-3.0.json delete mode 100644 schema/workfile-1.0.json diff --git a/schema/application-1.0.json b/schema/application-1.0.json deleted file mode 100644 index 953abee569..0000000000 --- a/schema/application-1.0.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:application-1.0", - "description": "An application definition.", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "label", - "application_dir", - "executable" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "label": { - "description": "Nice name of application.", - "type": "string" - }, - "application_dir": { - "description": "Name of directory used for application resources.", - "type": "string" - }, - "executable": { - "description": "Name of callable executable, this is called to launch the application", - "type": "string" - }, - "description": { - "description": "Description of application.", - "type": "string" - }, - "environment": { - "description": "Key/value pairs for environment variables related to this application. Supports lists for paths, such as PYTHONPATH.", - "type": "object", - "items": { - "oneOf": [ - {"type": "string"}, - {"type": "array", "items": {"type": "string"}} - ] - } - }, - "default_dirs": { - "type": "array", - "items": { - "type": "string" - } - }, - "copy": { - "type": "object", - "patternProperties": { - "^.*$": { - "anyOf": [ - {"type": "string"}, - {"type": "null"} - ] - } - }, - "additionalProperties": false - } - } -} diff --git a/schema/asset-1.0.json b/schema/asset-1.0.json deleted file mode 100644 index ab104c002a..0000000000 --- a/schema/asset-1.0.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:asset-1.0", - "description": "A unit of data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "name", - "subsets" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "name": { - "description": "Name of directory", - "type": "string" - }, - "subsets": { - "type": "array", - "items": { - "$ref": "subset.json" - } - } - }, - - "definitions": {} -} diff --git a/schema/asset-2.0.json b/schema/asset-2.0.json deleted file mode 100644 index b894d79792..0000000000 --- a/schema/asset-2.0.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:asset-2.0", - "description": "A unit of data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "name", - "silo", - "data" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:asset-2.0"], - "example": "openpype:asset-2.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["asset"], - "example": "asset" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of asset", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "Bruce" - }, - "silo": { - "description": "Group or container of asset", - "type": "string", - "example": "assets" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": {"key": "value"} - } - }, - - "definitions": {} -} diff --git a/schema/asset-3.0.json b/schema/asset-3.0.json deleted file mode 100644 index 948704d2a1..0000000000 --- a/schema/asset-3.0.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:asset-3.0", - "description": "A unit of data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "name", - "data" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:asset-3.0"], - "example": "openpype:asset-3.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["asset"], - "example": "asset" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of asset", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "Bruce" - }, - "silo": { - "description": "Group or container of asset", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "assets" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": {"key": "value"} - } - }, - - "definitions": {} -} diff --git a/schema/config-1.0.json b/schema/config-1.0.json deleted file mode 100644 index 49398a57cd..0000000000 --- a/schema/config-1.0.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:config-1.0", - "description": "A project configuration.", - - "type": "object", - - "additionalProperties": false, - "required": [ - "tasks", - "apps" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "template": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^.*$": { - "type": "string" - } - } - }, - "tasks": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "group": {"type": "string"}, - "label": {"type": "string"} - }, - "required": ["name"] - } - }, - "apps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "group": {"type": "string"}, - "label": {"type": "string"} - }, - "required": ["name"] - } - }, - "families": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "label": {"type": "string"}, - "hideFilter": {"type": "boolean"} - }, - "required": ["name"] - } - }, - "groups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "color": {"type": "string"}, - "order": {"type": ["integer", "number"]} - }, - "required": ["name"] - } - }, - "copy": { - "type": "object" - } - } -} diff --git a/schema/config-1.1.json b/schema/config-1.1.json deleted file mode 100644 index 6e15514aaf..0000000000 --- a/schema/config-1.1.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:config-1.1", - "description": "A project configuration.", - - "type": "object", - - "additionalProperties": false, - "required": [ - "tasks", - "apps" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "template": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^.*$": { - "type": "string" - } - } - }, - "tasks": { - "type": "object", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "group": {"type": "string"}, - "label": {"type": "string"} - }, - "required": [ - "short_name" - ] - } - }, - "apps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "group": {"type": "string"}, - "label": {"type": "string"} - }, - "required": ["name"] - } - }, - "families": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "label": {"type": "string"}, - "hideFilter": {"type": "boolean"} - }, - "required": ["name"] - } - }, - "groups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "color": {"type": "string"}, - "order": {"type": ["integer", "number"]} - }, - "required": ["name"] - } - }, - "copy": { - "type": "object" - } - } -} diff --git a/schema/config-2.0.json b/schema/config-2.0.json deleted file mode 100644 index 54b226711a..0000000000 --- a/schema/config-2.0.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:config-2.0", - "description": "A project configuration.", - - "type": "object", - - "additionalProperties": false, - "required": [ - "tasks", - "apps" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "templates": { - "type": "object" - }, - "roots": { - "type": "object" - }, - "imageio": { - "type": "object" - }, - "tasks": { - "type": "object", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "group": {"type": "string"}, - "label": {"type": "string"} - }, - "required": [ - "short_name" - ] - } - }, - "apps": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "group": {"type": "string"}, - "label": {"type": "string"} - }, - "required": ["name"] - } - }, - "families": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "label": {"type": "string"}, - "hideFilter": {"type": "boolean"} - }, - "required": ["name"] - } - }, - "groups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "icon": {"type": "string"}, - "color": {"type": "string"}, - "order": {"type": ["integer", "number"]} - }, - "required": ["name"] - } - }, - "copy": { - "type": "object" - } - } -} diff --git a/schema/container-1.0.json b/schema/container-1.0.json deleted file mode 100644 index 012e8499e6..0000000000 --- a/schema/container-1.0.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:container-1.0", - "description": "A loaded asset", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "id", - "objectName", - "name", - "author", - "loader", - "families", - "time", - "subset", - "asset", - "representation", - "version", - "silo", - "path", - "source" - ], - "properties": { - "id": { - "description": "Identifier for finding object in host", - "type": "string", - "enum": ["pyblish.mindbender.container"], - "example": "pyblish.mindbender.container" - }, - "objectName": { - "description": "Name of internal object, such as the objectSet in Maya.", - "type": "string", - "example": "Bruce_:rigDefault_CON" - }, - "name": { - "description": "Full name of application object", - "type": "string", - "example": "modelDefault" - }, - "author": { - "description": "Name of the author of the published version", - "type": "string", - "example": "Marcus Ottosson" - }, - "loader": { - "description": "Name of loader plug-in used to produce this container", - "type": "string", - "example": "ModelLoader" - }, - "families": { - "description": "Families associated with the this subset", - "type": "string", - "example": "mindbender.model" - }, - "time": { - "description": "File-system safe, formatted time", - "type": "string", - "example": "20170329T131545Z" - }, - "subset": { - "description": "Name of source subset", - "type": "string", - "example": "modelDefault" - }, - "asset": { - "description": "Name of source asset", - "type": "string" , - "example": "Bruce" - }, - "representation": { - "description": "Name of source representation", - "type": "string" , - "example": ".ma" - }, - "version": { - "description": "Version number", - "type": "number", - "example": 12 - }, - "silo": { - "description": "Silo of parent asset", - "type": "string", - "example": "assets" - }, - "path": { - "description": "Absolute path on disk", - "type": "string", - "example": "{root}/assets/Bruce/publish/rigDefault/v002" - }, - "source": { - "description": "Absolute path to file from which this version was published", - "type": "string", - "example": "{root}/assets/Bruce/work/rigging/maya/scenes/rig_v001.ma" - } - } -} diff --git a/schema/container-2.0.json b/schema/container-2.0.json deleted file mode 100644 index 1673ee5d1d..0000000000 --- a/schema/container-2.0.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:container-2.0", - "description": "A loaded asset", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "id", - "objectName", - "name", - "namespace", - "loader", - "representation" - ], - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:container-2.0"], - "example": "openpype:container-2.0" - }, - "id": { - "description": "Identifier for finding object in host", - "type": "string", - "enum": ["pyblish.avalon.container"], - "example": "pyblish.avalon.container" - }, - "objectName": { - "description": "Name of internal object, such as the objectSet in Maya.", - "type": "string", - "example": "Bruce_:rigDefault_CON" - }, - "loader": { - "description": "Name of loader plug-in used to produce this container", - "type": "string", - "example": "ModelLoader" - }, - "name": { - "description": "Internal object name of container in application", - "type": "string", - "example": "modelDefault_01" - }, - "namespace": { - "description": "Internal namespace of container in application", - "type": "string", - "example": "Bruce_" - }, - "representation": { - "description": "Unique id of representation in database", - "type": "string", - "example": "59523f355f8c1b5f6c5e8348" - } - } -} diff --git a/schema/hero_version-1.0.json b/schema/hero_version-1.0.json deleted file mode 100644 index b720dc2887..0000000000 --- a/schema/hero_version-1.0.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:hero_version-1.0", - "description": "Hero version of asset", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "version_id", - "schema", - "type", - "parent" - ], - - "properties": { - "_id": { - "description": "Document's id (database will create it's if not entered)", - "example": "ObjectId(592c33475f8c1b064c4d1696)" - }, - "version_id": { - "description": "The version ID from which it was created", - "example": "ObjectId(592c33475f8c1b064c4d1695)" - }, - "schema": { - "description": "The schema associated with this document", - "type": "string", - "enum": ["openpype:hero_version-1.0"], - "example": "openpype:hero_version-1.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["hero_version"], - "example": "hero_version" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "ObjectId(592c33475f8c1b064c4d1697)" - } - } -} diff --git a/schema/inventory-1.0.json b/schema/inventory-1.0.json deleted file mode 100644 index 2fe78794ab..0000000000 --- a/schema/inventory-1.0.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:config-1.0", - "description": "A project configuration.", - - "type": "object", - - "additionalProperties": true -} diff --git a/schema/inventory-1.1.json b/schema/inventory-1.1.json deleted file mode 100644 index b61a76b32a..0000000000 --- a/schema/inventory-1.1.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:config-1.1", - "description": "A project configuration.", - - "type": "object", - - "additionalProperties": true -} diff --git a/schema/project-2.0.json b/schema/project-2.0.json deleted file mode 100644 index 0ed5a55599..0000000000 --- a/schema/project-2.0.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:project-2.0", - "description": "A unit of data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "name", - "data", - "config" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:project-2.0"], - "example": "openpype:project-2.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["project"], - "example": "project" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of directory", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "hulk" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": { - "fps": 24, - "width": 1920, - "height": 1080 - } - }, - "config": { - "type": "object", - "description": "Document metadata", - "example": { - "schema": "openpype:config-1.0", - "apps": [ - { - "name": "maya2016", - "label": "Autodesk Maya 2016" - }, - { - "name": "nuke10", - "label": "The Foundry Nuke 10.0" - } - ], - "tasks": [ - {"name": "model"}, - {"name": "render"}, - {"name": "animate"}, - {"name": "rig"}, - {"name": "lookdev"}, - {"name": "layout"} - ], - "template": { - "work": - "{root}/{project}/{silo}/{asset}/work/{task}/{app}", - "publish": - "{root}/{project}/{silo}/{asset}/publish/{subset}/v{version:0>3}/{subset}.{representation}" - } - }, - "$ref": "config-1.0.json" - } - }, - - "definitions": {} -} diff --git a/schema/project-2.1.json b/schema/project-2.1.json deleted file mode 100644 index 9413c9f691..0000000000 --- a/schema/project-2.1.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:project-2.1", - "description": "A unit of data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "name", - "data", - "config" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:project-2.1"], - "example": "openpype:project-2.1" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["project"], - "example": "project" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of directory", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "hulk" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": { - "fps": 24, - "width": 1920, - "height": 1080 - } - }, - "config": { - "type": "object", - "description": "Document metadata", - "example": { - "schema": "openpype:config-1.1", - "apps": [ - { - "name": "maya2016", - "label": "Autodesk Maya 2016" - }, - { - "name": "nuke10", - "label": "The Foundry Nuke 10.0" - } - ], - "tasks": { - "Model": {"short_name": "mdl"}, - "Render": {"short_name": "rnd"}, - "Animate": {"short_name": "anim"}, - "Rig": {"short_name": "rig"}, - "Lookdev": {"short_name": "look"}, - "Layout": {"short_name": "lay"} - }, - "template": { - "work": - "{root}/{project}/{silo}/{asset}/work/{task}/{app}", - "publish": - "{root}/{project}/{silo}/{asset}/publish/{subset}/v{version:0>3}/{subset}.{representation}" - } - }, - "$ref": "config-1.1.json" - } - }, - - "definitions": {} -} diff --git a/schema/project-3.0.json b/schema/project-3.0.json deleted file mode 100644 index be23e10c93..0000000000 --- a/schema/project-3.0.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:project-3.0", - "description": "A unit of data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "name", - "data", - "config" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:project-3.0"], - "example": "openpype:project-3.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["project"], - "example": "project" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of directory", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "hulk" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": { - "fps": 24, - "width": 1920, - "height": 1080 - } - }, - "config": { - "type": "object", - "description": "Document metadata", - "$ref": "config-2.0.json" - } - }, - - "definitions": {} -} diff --git a/schema/representation-1.0.json b/schema/representation-1.0.json deleted file mode 100644 index 347c585f52..0000000000 --- a/schema/representation-1.0.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:representation-1.0", - "description": "The inverse of an instance", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "format", - "path" - ], - - "properties": { - "schema": {"type": "string"}, - "format": { - "description": "File extension, including '.'", - "type": "string" - }, - "path": { - "description": "Unformatted path to version.", - "type": "string" - } - } -} diff --git a/schema/representation-2.0.json b/schema/representation-2.0.json deleted file mode 100644 index f47c16a10a..0000000000 --- a/schema/representation-2.0.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:representation-2.0", - "description": "The inverse of an instance", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "parent", - "name", - "data" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:representation-2.0"], - "example": "openpype:representation-2.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["representation"], - "example": "representation" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of representation", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "abc" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": { - "label": "Alembic" - } - }, - "dependencies": { - "description": "Other representation that this representation depends on", - "type": "array", - "items": {"type": "string"}, - "example": [ - "592d547a5f8c1b388093c145" - ] - }, - "context": { - "description": "Summary of the context to which this representation belong.", - "type": "object", - "properties": { - "project": {"type": "object"}, - "asset": {"type": "string"}, - "silo": {"type": ["string", "null"]}, - "subset": {"type": "string"}, - "version": {"type": "number"}, - "representation": {"type": "string"} - }, - "example": { - "project": "hulk", - "asset": "Bruce", - "silo": "assets", - "subset": "rigDefault", - "version": 12, - "representation": "ma" - } - } - } -} diff --git a/schema/session-1.0.json b/schema/session-1.0.json deleted file mode 100644 index 5ced0a6f08..0000000000 --- a/schema/session-1.0.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:session-1.0", - "description": "The Avalon environment", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "AVALON_PROJECTS", - "AVALON_PROJECT", - "AVALON_ASSET", - "AVALON_SILO", - "AVALON_CONFIG" - ], - - "properties": { - "AVALON_PROJECTS": { - "description": "Absolute path to root of project directories", - "type": "string", - "example": "/nas/projects" - }, - "AVALON_PROJECT": { - "description": "Name of project", - "type": "string", - "pattern": "^\\w*$", - "example": "Hulk" - }, - "AVALON_ASSET": { - "description": "Name of asset", - "type": "string", - "pattern": "^\\w*$", - "example": "Bruce" - }, - "AVALON_SILO": { - "description": "Name of asset group or container", - "type": "string", - "pattern": "^\\w*$", - "example": "assets" - }, - "AVALON_TASK": { - "description": "Name of task", - "type": "string", - "pattern": "^\\w*$", - "example": "modeling" - }, - "AVALON_CONFIG": { - "description": "Name of Avalon configuration", - "type": "string", - "pattern": "^\\w*$", - "example": "polly" - }, - "AVALON_APP": { - "description": "Name of application", - "type": "string", - "pattern": "^\\w*$", - "example": "maya2016" - }, - "AVALON_MONGO": { - "description": "Address to the asset database", - "type": "string", - "pattern": "^mongodb://[\\w/@:.]*$", - "example": "mongodb://localhost:27017", - "default": "mongodb://localhost:27017" - }, - "AVALON_DB": { - "description": "Name of database", - "type": "string", - "pattern": "^\\w*$", - "example": "avalon", - "default": "avalon" - }, - "AVALON_LABEL": { - "description": "Nice name of Avalon, used in e.g. graphical user interfaces", - "type": "string", - "example": "Mindbender", - "default": "Avalon" - }, - "AVALON_SENTRY": { - "description": "Address to Sentry", - "type": "string", - "pattern": "^http[\\w/@:.]*$", - "example": "https://5b872b280de742919b115bdc8da076a5:8d278266fe764361b8fa6024af004a9c@logs.mindbender.com/2", - "default": null - }, - "AVALON_DEADLINE": { - "description": "Address to Deadline", - "type": "string", - "pattern": "^http[\\w/@:.]*$", - "example": "http://192.168.99.101", - "default": null - }, - "AVALON_TIMEOUT": { - "description": "Wherever there is a need for a timeout, this is the default value.", - "type": "string", - "pattern": "^[0-9]*$", - "default": "1000", - "example": "1000" - }, - "AVALON_UPLOAD": { - "description": "Boolean of whether to upload published material to central asset repository", - "type": "string", - "default": null, - "example": "True" - }, - "AVALON_USERNAME": { - "description": "Generic username", - "type": "string", - "pattern": "^\\w*$", - "default": "avalon", - "example": "myself" - }, - "AVALON_PASSWORD": { - "description": "Generic password", - "type": "string", - "pattern": "^\\w*$", - "default": "secret", - "example": "abc123" - }, - "AVALON_INSTANCE_ID": { - "description": "Unique identifier for instances in a working file", - "type": "string", - "pattern": "^[\\w.]*$", - "default": "avalon.instance", - "example": "avalon.instance" - }, - "AVALON_CONTAINER_ID": { - "description": "Unique identifier for a loaded representation in a working file", - "type": "string", - "pattern": "^[\\w.]*$", - "default": "avalon.container", - "example": "avalon.container" - }, - "AVALON_DEBUG": { - "description": "Enable debugging mode. Some applications may use this for e.g. extended verbosity or mock plug-ins.", - "type": "string", - "default": null, - "example": "True" - } - } -} diff --git a/schema/session-2.0.json b/schema/session-2.0.json deleted file mode 100644 index 0a4d51beb2..0000000000 --- a/schema/session-2.0.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:session-2.0", - "description": "The Avalon environment", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "AVALON_PROJECT", - "AVALON_ASSET", - "AVALON_CONFIG" - ], - - "properties": { - "AVALON_PROJECTS": { - "description": "Absolute path to root of project directories", - "type": "string", - "example": "/nas/projects" - }, - "AVALON_PROJECT": { - "description": "Name of project", - "type": "string", - "pattern": "^\\w*$", - "example": "Hulk" - }, - "AVALON_ASSET": { - "description": "Name of asset", - "type": "string", - "pattern": "^\\w*$", - "example": "Bruce" - }, - "AVALON_SILO": { - "description": "Name of asset group or container", - "type": "string", - "pattern": "^\\w*$", - "example": "assets" - }, - "AVALON_TASK": { - "description": "Name of task", - "type": "string", - "pattern": "^\\w*$", - "example": "modeling" - }, - "AVALON_CONFIG": { - "description": "Name of Avalon configuration", - "type": "string", - "pattern": "^\\w*$", - "example": "polly" - }, - "AVALON_APP": { - "description": "Name of application", - "type": "string", - "pattern": "^\\w*$", - "example": "maya2016" - }, - "AVALON_DB": { - "description": "Name of database", - "type": "string", - "pattern": "^\\w*$", - "example": "avalon", - "default": "avalon" - }, - "AVALON_LABEL": { - "description": "Nice name of Avalon, used in e.g. graphical user interfaces", - "type": "string", - "example": "Mindbender", - "default": "Avalon" - }, - "AVALON_SENTRY": { - "description": "Address to Sentry", - "type": "string", - "pattern": "^http[\\w/@:.]*$", - "example": "https://5b872b280de742919b115bdc8da076a5:8d278266fe764361b8fa6024af004a9c@logs.mindbender.com/2", - "default": null - }, - "AVALON_DEADLINE": { - "description": "Address to Deadline", - "type": "string", - "pattern": "^http[\\w/@:.]*$", - "example": "http://192.168.99.101", - "default": null - }, - "AVALON_TIMEOUT": { - "description": "Wherever there is a need for a timeout, this is the default value.", - "type": "string", - "pattern": "^[0-9]*$", - "default": "1000", - "example": "1000" - }, - "AVALON_UPLOAD": { - "description": "Boolean of whether to upload published material to central asset repository", - "type": "string", - "default": null, - "example": "True" - }, - "AVALON_USERNAME": { - "description": "Generic username", - "type": "string", - "pattern": "^\\w*$", - "default": "avalon", - "example": "myself" - }, - "AVALON_PASSWORD": { - "description": "Generic password", - "type": "string", - "pattern": "^\\w*$", - "default": "secret", - "example": "abc123" - }, - "AVALON_INSTANCE_ID": { - "description": "Unique identifier for instances in a working file", - "type": "string", - "pattern": "^[\\w.]*$", - "default": "avalon.instance", - "example": "avalon.instance" - }, - "AVALON_CONTAINER_ID": { - "description": "Unique identifier for a loaded representation in a working file", - "type": "string", - "pattern": "^[\\w.]*$", - "default": "avalon.container", - "example": "avalon.container" - }, - "AVALON_DEBUG": { - "description": "Enable debugging mode. Some applications may use this for e.g. extended verbosity or mock plug-ins.", - "type": "string", - "default": null, - "example": "True" - } - } -} diff --git a/schema/session-3.0.json b/schema/session-3.0.json deleted file mode 100644 index 9f785939e4..0000000000 --- a/schema/session-3.0.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:session-3.0", - "description": "The Avalon environment", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "AVALON_PROJECT", - "AVALON_ASSET" - ], - - "properties": { - "AVALON_PROJECTS": { - "description": "Absolute path to root of project directories", - "type": "string", - "example": "/nas/projects" - }, - "AVALON_PROJECT": { - "description": "Name of project", - "type": "string", - "pattern": "^\\w*$", - "example": "Hulk" - }, - "AVALON_ASSET": { - "description": "Name of asset", - "type": "string", - "pattern": "^\\w*$", - "example": "Bruce" - }, - "AVALON_TASK": { - "description": "Name of task", - "type": "string", - "pattern": "^\\w*$", - "example": "modeling" - }, - "AVALON_APP": { - "description": "Name of host", - "type": "string", - "pattern": "^\\w*$", - "example": "maya2016" - }, - "AVALON_DB": { - "description": "Name of database", - "type": "string", - "pattern": "^\\w*$", - "example": "avalon", - "default": "avalon" - }, - "AVALON_LABEL": { - "description": "Nice name of Avalon, used in e.g. graphical user interfaces", - "type": "string", - "example": "Mindbender", - "default": "Avalon" - }, - "AVALON_TIMEOUT": { - "description": "Wherever there is a need for a timeout, this is the default value.", - "type": "string", - "pattern": "^[0-9]*$", - "default": "1000", - "example": "1000" - }, - "AVALON_INSTANCE_ID": { - "description": "Unique identifier for instances in a working file", - "type": "string", - "pattern": "^[\\w.]*$", - "default": "avalon.instance", - "example": "avalon.instance" - }, - "AVALON_CONTAINER_ID": { - "description": "Unique identifier for a loaded representation in a working file", - "type": "string", - "pattern": "^[\\w.]*$", - "default": "avalon.container", - "example": "avalon.container" - } - } -} diff --git a/schema/shaders-1.0.json b/schema/shaders-1.0.json deleted file mode 100644 index 7102ba1861..0000000000 --- a/schema/shaders-1.0.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:shaders-1.0", - "description": "Relationships between shaders and Avalon IDs", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "shader" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "shader": { - "description": "Name of directory", - "type": "array", - "items": { - "type": "str", - "description": "Avalon ID and optional face indexes, e.g. 'f9520572-ac1d-11e6-b39e-3085a99791c9.f[5002:5185]'" - } - } - }, - - "definitions": {} -} diff --git a/schema/subset-1.0.json b/schema/subset-1.0.json deleted file mode 100644 index a299a6d341..0000000000 --- a/schema/subset-1.0.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:subset-1.0", - "description": "A container of instances", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "name", - "versions" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string" - }, - "name": { - "description": "Name of directory", - "type": "string" - }, - "versions": { - "type": "array", - "items": { - "$ref": "version.json" - } - } - }, - - "definitions": {} -} diff --git a/schema/subset-2.0.json b/schema/subset-2.0.json deleted file mode 100644 index db256ec7fb..0000000000 --- a/schema/subset-2.0.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:subset-2.0", - "description": "A container of instances", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "parent", - "name", - "data" - ], - - "properties": { - "schema": { - "description": "The schema associated with this document", - "type": "string", - "enum": ["openpype:subset-2.0"], - "example": "openpype:subset-2.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["subset"], - "example": "subset" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of directory", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "shot01" - }, - "data": { - "type": "object", - "description": "Document metadata", - "example": { - "frameStart": 1000, - "frameEnd": 1201 - } - } - } -} diff --git a/schema/subset-3.0.json b/schema/subset-3.0.json deleted file mode 100644 index 1a0db53c04..0000000000 --- a/schema/subset-3.0.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:subset-3.0", - "description": "A container of instances", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "parent", - "name", - "data" - ], - - "properties": { - "schema": { - "description": "The schema associated with this document", - "type": "string", - "enum": ["openpype:subset-3.0"], - "example": "openpype:subset-3.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["subset"], - "example": "subset" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Name of directory", - "type": "string", - "pattern": "^[a-zA-Z0-9_.]*$", - "example": "shot01" - }, - "data": { - "description": "Document metadata", - "type": "object", - "required": ["families"], - "properties": { - "families": { - "type": "array", - "items": {"type": "string"}, - "description": "One or more families associated with this subset" - } - }, - "example": { - "families" : [ - "avalon.camera" - ], - "frameStart": 1000, - "frameEnd": 1201 - } - } - } -} diff --git a/schema/thumbnail-1.0.json b/schema/thumbnail-1.0.json deleted file mode 100644 index 5bdf78a4b1..0000000000 --- a/schema/thumbnail-1.0.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:thumbnail-1.0", - "description": "Entity with thumbnail data", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "data" - ], - - "properties": { - "schema": { - "description": "The schema associated with this document", - "type": "string", - "enum": ["openpype:thumbnail-1.0"], - "example": "openpype:thumbnail-1.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["thumbnail"], - "example": "thumbnail" - }, - "data": { - "description": "Thumbnail data", - "type": "object", - "example": { - "binary_data": "Binary({byte data of image})", - "template": "{thumbnail_root}/{project[name]}/{_id}{ext}}", - "template_data": { - "ext": ".jpg" - } - } - } - } -} diff --git a/schema/version-1.0.json b/schema/version-1.0.json deleted file mode 100644 index daa1997721..0000000000 --- a/schema/version-1.0.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:version-1.0", - "description": "An individual version", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "version", - "path", - "time", - "author", - "source", - "representations" - ], - - "properties": { - "schema": {"type": "string"}, - "representations": { - "type": "array", - "items": { - "$ref": "representation.json" - } - }, - "time": { - "description": "ISO formatted, file-system compatible time", - "type": "string" - }, - "author": { - "description": "User logged on to the machine at time of publish", - "type": "string" - }, - "version": { - "description": "Number of this version", - "type": "number" - }, - "path": { - "description": "Unformatted path, e.g. '{root}/assets/Bruce/publish/lookdevDefault/v001", - "type": "string" - }, - "source": { - "description": "Original file from which this version was made.", - "type": "string" - } - } -} diff --git a/schema/version-2.0.json b/schema/version-2.0.json deleted file mode 100644 index 099e9be70a..0000000000 --- a/schema/version-2.0.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:version-2.0", - "description": "An individual version", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "parent", - "name", - "data" - ], - - "properties": { - "schema": { - "description": "The schema associated with this document", - "type": "string", - "enum": ["openpype:version-2.0"], - "example": "openpype:version-2.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["version"], - "example": "version" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Number of version", - "type": "number", - "example": 12 - }, - "locations": { - "description": "Where on the planet this version can be found.", - "type": "array", - "items": {"type": "string"}, - "example": ["data.avalon.com"] - }, - "data": { - "description": "Document metadata", - "type": "object", - "required": ["families", "author", "source", "time"], - "properties": { - "time": { - "description": "ISO formatted, file-system compatible time", - "type": "string" - }, - "timeFormat": { - "description": "ISO format of time", - "type": "string" - }, - "author": { - "description": "User logged on to the machine at time of publish", - "type": "string" - }, - "version": { - "description": "Number of this version", - "type": "number" - }, - "path": { - "description": "Unformatted path, e.g. '{root}/assets/Bruce/publish/lookdevDefault/v001", - "type": "string" - }, - "source": { - "description": "Original file from which this version was made.", - "type": "string" - }, - "families": { - "type": "array", - "items": {"type": "string"}, - "description": "One or more families associated with this version" - } - }, - "example": { - "source" : "{root}/f02_prod/assets/BubbleWitch/work/modeling/marcus/maya/scenes/model_v001.ma", - "author" : "marcus", - "families" : [ - "avalon.model" - ], - "time" : "20170510T090203Z" - } - } - } -} diff --git a/schema/version-3.0.json b/schema/version-3.0.json deleted file mode 100644 index 3e07fc4499..0000000000 --- a/schema/version-3.0.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:version-3.0", - "description": "An individual version", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "parent", - "name", - "data" - ], - - "properties": { - "schema": { - "description": "The schema associated with this document", - "type": "string", - "enum": ["openpype:version-3.0"], - "example": "openpype:version-3.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["version"], - "example": "version" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "name": { - "description": "Number of version", - "type": "number", - "example": 12 - }, - "locations": { - "description": "Where on the planet this version can be found.", - "type": "array", - "items": {"type": "string"}, - "example": ["data.avalon.com"] - }, - "data": { - "description": "Document metadata", - "type": "object", - "required": ["author", "source", "time"], - "properties": { - "time": { - "description": "ISO formatted, file-system compatible time", - "type": "string" - }, - "timeFormat": { - "description": "ISO format of time", - "type": "string" - }, - "author": { - "description": "User logged on to the machine at time of publish", - "type": "string" - }, - "version": { - "description": "Number of this version", - "type": "number" - }, - "path": { - "description": "Unformatted path, e.g. '{root}/assets/Bruce/publish/lookdevDefault/v001", - "type": "string" - }, - "source": { - "description": "Original file from which this version was made.", - "type": "string" - } - }, - "example": { - "source" : "{root}/f02_prod/assets/BubbleWitch/work/modeling/marcus/maya/scenes/model_v001.ma", - "author" : "marcus", - "time" : "20170510T090203Z" - } - } - } -} diff --git a/schema/workfile-1.0.json b/schema/workfile-1.0.json deleted file mode 100644 index 5f9600ef20..0000000000 --- a/schema/workfile-1.0.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - - "title": "openpype:workfile-1.0", - "description": "Workfile additional information.", - - "type": "object", - - "additionalProperties": true, - - "required": [ - "schema", - "type", - "filename", - "task_name", - "parent" - ], - - "properties": { - "schema": { - "description": "Schema identifier for payload", - "type": "string", - "enum": ["openpype:workfile-1.0"], - "example": "openpype:workfile-1.0" - }, - "type": { - "description": "The type of document", - "type": "string", - "enum": ["workfile"], - "example": "workfile" - }, - "parent": { - "description": "Unique identifier to parent document", - "example": "592c33475f8c1b064c4d1696" - }, - "filename": { - "description": "Workfile's filename", - "type": "string", - "example": "kuba_each_case_Alpaca_01_animation_v001.ma" - }, - "task_name": { - "description": "Task name", - "type": "string", - "example": "animation" - }, - "data": { - "description": "Document metadata", - "type": "object", - "example": {"key": "value"} - } - } -} diff --git a/setup.py b/setup.py index 4b6f286730..6179de1d34 100644 --- a/setup.py +++ b/setup.py @@ -124,7 +124,6 @@ bin_includes = [ include_files = [ "igniter", "openpype", - "schema", "LICENSE", "README.md" ] From 975d09d66868d76dad1eb356539389700eb35c99 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 30 Aug 2023 14:29:16 +0200 Subject: [PATCH 092/103] lower urllib3 to support older OpenSSL than 1.1.1 --- poetry.lock | 15 +++++++-------- pyproject.toml | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5621d39988..5e88f5b93c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3372,21 +3372,20 @@ files = [ [[package]] name = "urllib3" -version = "2.0.2" +version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, + {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, + {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" diff --git a/pyproject.toml b/pyproject.toml index b394a895e3..e2d35f3c6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ QtPy = "^2.3.0" qtawesome = "0.7.3" speedcopy = "^2.1" six = "^1.15" +urllib3 = "1.26.16" semver = "^2.13.0" # for version resolution wsrpc_aiohttp = "^3.1.1" # websocket server pywin32 = { version = "301", markers = "sys_platform == 'win32'" } From b1796d6603c3ff74aaf9798e14f9b4e08e0c9c3a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 4 Sep 2023 11:19:33 +0200 Subject: [PATCH 093/103] do not add schema to zip files --- igniter/bootstrap_repos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/igniter/bootstrap_repos.py b/igniter/bootstrap_repos.py index 408764e1a8..e7b440f812 100644 --- a/igniter/bootstrap_repos.py +++ b/igniter/bootstrap_repos.py @@ -589,7 +589,7 @@ class BootstrapRepos: self.registry = OpenPypeSettingsRegistry() self.zip_filter = [".pyc", "__pycache__"] self.openpype_filter = [ - "openpype", "schema", "LICENSE" + "openpype", "LICENSE" ] # dummy progress reporter From b4aa3b15dfbac86834fdf6dad796672634802363 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:31:44 +0200 Subject: [PATCH 094/103] do not override scale factor rounding policy if has defined value through env variable --- igniter/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/igniter/__init__.py b/igniter/__init__.py index 16ffb940f6..085a825860 100644 --- a/igniter/__init__.py +++ b/igniter/__init__.py @@ -34,7 +34,11 @@ def _get_qt_app(): if attr is not None: QtWidgets.QApplication.setAttribute(attr) - if hasattr(QtWidgets.QApplication, "setHighDpiScaleFactorRoundingPolicy"): + policy = os.getenv("QT_SCALE_FACTOR_ROUNDING_POLICY") + if ( + hasattr(QtWidgets.QApplication, "setHighDpiScaleFactorRoundingPolicy") + and not policy + ): QtWidgets.QApplication.setHighDpiScaleFactorRoundingPolicy( QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough ) From 3e9528b5e06e9de103f0b71f1ab1d063635083e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:41:32 +0000 Subject: [PATCH 095/103] Bump certifi from 2023.5.7 to 2023.7.22 Bumps [certifi](https://github.com/certifi/python-certifi) from 2023.5.7 to 2023.7.22. - [Commits](https://github.com/certifi/python-certifi/compare/2023.05.07...2023.07.22) --- updated-dependencies: - dependency-name: certifi dependency-type: indirect ... Signed-off-by: dependabot[bot] --- poetry.lock | 178 ++-------------------------------------------------- 1 file changed, 6 insertions(+), 172 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5e88f5b93c..2b9fab4bc4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "acre" version = "1.0.0" description = "Lightweight cross-platform environment management Python package that makes it trivial to launch applications in their own configurable working environment." -category = "main" optional = false python-versions = ">=2.7" files = [] @@ -20,7 +19,6 @@ resolved_reference = "126f7a188cfe36718f707f42ebbc597e86aa86c3" name = "aiohttp" version = "3.8.4" description = "Async http client/server framework (asyncio)" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -129,7 +127,6 @@ speedups = ["Brotli", "aiodns", "cchardet"] name = "aiohttp-json-rpc" version = "0.13.3" description = "Implementation JSON-RPC 2.0 server and client using aiohttp on top of websockets transport" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -144,7 +141,6 @@ aiohttp = ">=3,<4" name = "aiohttp-middlewares" version = "2.2.0" description = "Collection of useful middlewares for aiohttp applications." -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -161,7 +157,6 @@ yarl = ">=1.5.1,<2.0.0" name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -176,7 +171,6 @@ frozenlist = ">=1.1.0" name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -188,7 +182,6 @@ files = [ name = "ansicon" version = "1.89.0" description = "Python wrapper for loading Jason Hood's ANSICON" -category = "main" optional = false python-versions = "*" files = [ @@ -200,7 +193,6 @@ files = [ name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [] @@ -216,7 +208,6 @@ resolved_reference = "8734277956c1df3b85385e6b308e954910533884" name = "arrow" version = "0.17.0" description = "Better dates & times for Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -231,7 +222,6 @@ python-dateutil = ">=2.7.0" name = "astroid" version = "2.15.5" description = "An abstract syntax tree for Python with inference support." -category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -248,7 +238,6 @@ wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""} name = "async-timeout" version = "4.0.2" description = "Timeout context manager for asyncio programs" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -260,7 +249,6 @@ files = [ name = "atomicwrites" version = "1.4.1" description = "Atomic file writes." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -271,7 +259,6 @@ files = [ name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -290,7 +277,6 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte name = "autopep8" version = "2.0.2" description = "A tool that automatically formats Python code to conform to the PEP 8 style guide" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -306,7 +292,6 @@ tomli = {version = "*", markers = "python_version < \"3.11\""} name = "babel" version = "2.12.1" description = "Internationalization utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -318,7 +303,6 @@ files = [ name = "bcrypt" version = "4.0.1" description = "Modern password hashing for your software and your servers" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -353,7 +337,6 @@ typecheck = ["mypy"] name = "bidict" version = "0.22.1" description = "The bidirectional mapping library for Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -370,7 +353,6 @@ test = ["hypothesis", "pytest", "pytest-benchmark[histogram]", "pytest-cov", "py name = "blessed" version = "1.20.0" description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." -category = "main" optional = false python-versions = ">=2.7" files = [ @@ -387,7 +369,6 @@ wcwidth = ">=0.1.4" name = "cachetools" version = "5.3.1" description = "Extensible memoizing collections and decorators" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -397,21 +378,19 @@ files = [ [[package]] name = "certifi" -version = "2023.5.7" +version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, ] [[package]] name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false python-versions = "*" files = [ @@ -488,7 +467,6 @@ pycparser = "*" name = "cfgv" version = "3.3.1" description = "Validate configuration and produce human readable error messages." -category = "dev" optional = false python-versions = ">=3.6.1" files = [ @@ -500,7 +478,6 @@ files = [ name = "charset-normalizer" version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -585,7 +562,6 @@ files = [ name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -600,7 +576,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "clique" version = "1.6.1" description = "Manage collections with common numerical component" -category = "main" optional = false python-versions = ">=2.7, <4.0" files = [ @@ -617,7 +592,6 @@ test = ["pytest (>=2.3.5,<5)", "pytest-cov (>=2,<3)", "pytest-runner (>=2.7,<3)" name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -629,7 +603,6 @@ files = [ name = "commonmark" version = "0.9.1" description = "Python parser for the CommonMark Markdown spec" -category = "dev" optional = false python-versions = "*" files = [ @@ -644,7 +617,6 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] name = "coolname" version = "2.2.0" description = "Random name and slug generator" -category = "main" optional = false python-versions = "*" files = [ @@ -656,7 +628,6 @@ files = [ name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -732,7 +703,6 @@ toml = ["tomli"] name = "cryptography" version = "39.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -776,7 +746,6 @@ test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0 name = "cx-freeze" version = "6.12.0" description = "Create standalone executables from Python scripts" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -834,7 +803,6 @@ test = ["nose (==1.3.7)", "pygments (>=2.11.2)", "pytest (>=7.0.1)", "pytest-cov name = "cx-logging" version = "3.1.0" description = "Python and C interfaces for logging" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -865,7 +833,6 @@ files = [ name = "dill" version = "0.3.6" description = "serialize all of python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -880,7 +847,6 @@ graph = ["objgraph (>=1.7.2)"] name = "distlib" version = "0.3.6" description = "Distribution utilities" -category = "dev" optional = false python-versions = "*" files = [ @@ -892,7 +858,6 @@ files = [ name = "dnspython" version = "2.3.0" description = "DNS toolkit" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -913,7 +878,6 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"] name = "docutils" version = "0.19" description = "Docutils -- Python Documentation Utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -925,7 +889,6 @@ files = [ name = "dropbox" version = "11.36.0" description = "Official Dropbox API Client" -category = "main" optional = false python-versions = "*" files = [ @@ -943,7 +906,6 @@ stone = ">=2" name = "enlighten" version = "1.11.2" description = "Enlighten Progress Bar" -category = "main" optional = false python-versions = "*" files = [ @@ -959,7 +921,6 @@ prefixed = ">=0.3.2" name = "evdev" version = "1.6.1" description = "Bindings to the Linux input handling subsystem" -category = "main" optional = false python-versions = "*" files = [ @@ -970,7 +931,6 @@ files = [ name = "filelock" version = "3.12.0" description = "A platform independent file lock." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -986,7 +946,6 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "p name = "flake8" version = "6.0.0" description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" optional = false python-versions = ">=3.8.1" files = [ @@ -1003,7 +962,6 @@ pyflakes = ">=3.0.0,<3.1.0" name = "frozenlist" version = "1.3.3" description = "A list-like structure which implements collections.abc.MutableSequence" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1087,7 +1045,6 @@ files = [ name = "ftrack-python-api" version = "2.5.0" description = "Python API for ftrack." -category = "main" optional = false python-versions = ">=2.7.9, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -1110,7 +1067,6 @@ websocket-client = ">=0.40.0,<1" name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" -category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1121,7 +1077,6 @@ files = [ name = "gazu" version = "0.9.3" description = "Gazu is a client for Zou, the API to store the data of your CG production." -category = "main" optional = false python-versions = ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*, != 3.4.*, != 3.5.*, != 3.6.1, != 3.6.2" files = [ @@ -1141,7 +1096,6 @@ test = ["pytest", "pytest-cov", "requests-mock"] name = "gitdb" version = "4.0.10" description = "Git Object Database" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1156,7 +1110,6 @@ smmap = ">=3.0.1,<6" name = "gitpython" version = "3.1.31" description = "GitPython is a Python library used to interact with Git repositories" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1171,7 +1124,6 @@ gitdb = ">=4.0.1,<5" name = "google-api-core" version = "2.11.0" description = "Google API client core library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1194,7 +1146,6 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0dev)"] name = "google-api-python-client" version = "1.12.11" description = "Google API Client Library for Python" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" files = [ @@ -1214,7 +1165,6 @@ uritemplate = ">=3.0.0,<4dev" name = "google-auth" version = "2.17.3" description = "Google Authentication Library" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" files = [ @@ -1239,7 +1189,6 @@ requests = ["requests (>=2.20.0,<3.0.0dev)"] name = "google-auth-httplib2" version = "0.1.0" description = "Google Authentication Library: httplib2 transport" -category = "main" optional = false python-versions = "*" files = [ @@ -1256,7 +1205,6 @@ six = "*" name = "googleapis-common-protos" version = "1.59.0" description = "Common protobufs used in Google APIs" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1274,7 +1222,6 @@ grpc = ["grpcio (>=1.44.0,<2.0.0dev)"] name = "httplib2" version = "0.22.0" description = "A comprehensive HTTP client library." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1289,7 +1236,6 @@ pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0 name = "identify" version = "2.5.24" description = "File identification library for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1304,7 +1250,6 @@ license = ["ukkonen"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1316,7 +1261,6 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1328,7 +1272,6 @@ files = [ name = "importlib-metadata" version = "6.6.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1348,7 +1291,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1360,7 +1302,6 @@ files = [ name = "isort" version = "5.12.0" description = "A Python utility / library to sort Python imports." -category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -1378,7 +1319,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "jedi" version = "0.13.3" description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1396,7 +1336,6 @@ testing = ["colorama", "docopt", "pytest (>=3.1.0)"] name = "jeepney" version = "0.8.0" description = "Low-level, pure Python DBus protocol wrapper." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1412,7 +1351,6 @@ trio = ["async_generator", "trio"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1430,7 +1368,6 @@ i18n = ["Babel (>=2.7)"] name = "jinxed" version = "1.2.0" description = "Jinxed Terminal Library" -category = "main" optional = false python-versions = "*" files = [ @@ -1445,7 +1382,6 @@ ansicon = {version = "*", markers = "platform_system == \"Windows\""} name = "jsonschema" version = "2.6.0" description = "An implementation of JSON Schema validation for Python" -category = "main" optional = false python-versions = "*" files = [ @@ -1460,7 +1396,6 @@ format = ["rfc3987", "strict-rfc3339", "webcolors"] name = "keyring" version = "22.4.0" description = "Store and access your passwords safely." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1482,7 +1417,6 @@ testing = ["pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=1.2. name = "lazy-object-proxy" version = "1.9.0" description = "A fast and thorough lazy object proxy." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1528,7 +1462,6 @@ files = [ name = "lief" version = "0.13.1" description = "Library to instrument executable formats" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1561,7 +1494,6 @@ files = [ name = "linkify-it-py" version = "2.0.2" description = "Links recognition library with FULL unicode support." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1582,7 +1514,6 @@ test = ["coverage", "pytest", "pytest-cov"] name = "log4mongo" version = "1.7.0" description = "mongo database handler for python logging" -category = "main" optional = false python-versions = "*" files = [ @@ -1596,7 +1527,6 @@ pymongo = "*" name = "m2r2" version = "0.3.3.post2" description = "Markdown and reStructuredText in a single file." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1612,7 +1542,6 @@ mistune = "0.8.4" name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1637,7 +1566,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.0.1" description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1716,7 +1644,6 @@ files = [ name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1728,7 +1655,6 @@ files = [ name = "mdit-py-plugins" version = "0.3.5" description = "Collection of plugins for markdown-it-py" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1748,7 +1674,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1760,7 +1685,6 @@ files = [ name = "mistune" version = "0.8.4" description = "The fastest markdown parser in pure Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -1772,7 +1696,6 @@ files = [ name = "multidict" version = "6.0.4" description = "multidict implementation" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1856,7 +1779,6 @@ files = [ name = "myst-parser" version = "0.18.1" description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1883,7 +1805,6 @@ testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" -category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -1898,7 +1819,6 @@ setuptools = "*" name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1910,7 +1830,6 @@ files = [ name = "paramiko" version = "3.2.0" description = "SSH2 protocol library" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1932,7 +1851,6 @@ invoke = ["invoke (>=2.0)"] name = "parso" version = "0.8.3" description = "A Python Parser" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1948,7 +1866,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "patchelf" version = "0.17.2.1" description = "A small utility to modify the dynamic linker and RPATH of ELF executables." -category = "dev" optional = false python-versions = "*" files = [ @@ -1968,7 +1885,6 @@ test = ["importlib-metadata", "pytest"] name = "pathlib2" version = "2.3.7.post1" description = "Object-oriented filesystem paths" -category = "main" optional = false python-versions = "*" files = [ @@ -1983,7 +1899,6 @@ six = "*" name = "pillow" version = "9.5.0" description = "Python Imaging Library (Fork)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2063,7 +1978,6 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa name = "platformdirs" version = "3.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2079,7 +1993,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2095,7 +2008,6 @@ testing = ["pytest", "pytest-benchmark"] name = "ply" version = "3.11" description = "Python Lex & Yacc" -category = "main" optional = false python-versions = "*" files = [ @@ -2107,7 +2019,6 @@ files = [ name = "pockets" version = "0.9.1" description = "A collection of helpful Python tools!" -category = "dev" optional = false python-versions = "*" files = [ @@ -2122,7 +2033,6 @@ six = ">=1.5.2" name = "pre-commit" version = "3.3.2" description = "A framework for managing and maintaining multi-language pre-commit hooks." -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2141,7 +2051,6 @@ virtualenv = ">=20.10.0" name = "prefixed" version = "0.7.0" description = "Prefixed alternative numeric library" -category = "main" optional = false python-versions = "*" files = [ @@ -2153,7 +2062,6 @@ files = [ name = "protobuf" version = "4.23.2" description = "" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2176,7 +2084,6 @@ files = [ name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2188,7 +2095,6 @@ files = [ name = "pyasn1" version = "0.5.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2200,7 +2106,6 @@ files = [ name = "pyasn1-modules" version = "0.3.0" description = "A collection of ASN.1-based protocols modules" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2215,7 +2120,6 @@ pyasn1 = ">=0.4.6,<0.6.0" name = "pyblish-base" version = "1.8.11" description = "Plug-in driven automation framework for content" -category = "main" optional = false python-versions = "*" files = [ @@ -2227,7 +2131,6 @@ files = [ name = "pycodestyle" version = "2.10.0" description = "Python style guide checker" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2239,7 +2142,6 @@ files = [ name = "pycparser" version = "2.21" description = "C parser in Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2251,7 +2153,6 @@ files = [ name = "pydocstyle" version = "6.3.0" description = "Python docstring style checker" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2269,7 +2170,6 @@ toml = ["tomli (>=1.2.3)"] name = "pyflakes" version = "3.0.1" description = "passive checker of Python programs" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2281,7 +2181,6 @@ files = [ name = "pygments" version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2296,7 +2195,6 @@ plugins = ["importlib-metadata"] name = "pylint" version = "2.17.4" description = "python code static checker" -category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -2323,7 +2221,6 @@ testutils = ["gitpython (>3)"] name = "pymongo" version = "3.13.0" description = "Python driver for MongoDB " -category = "main" optional = false python-versions = "*" files = [ @@ -2452,7 +2349,6 @@ zstd = ["zstandard"] name = "pynacl" version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2479,7 +2375,6 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] name = "pynput" version = "1.7.6" description = "Monitor and control user input devices" -category = "main" optional = false python-versions = "*" files = [ @@ -2498,7 +2393,6 @@ six = "*" name = "pyobjc-core" version = "9.1.1" description = "Python<->ObjC Interoperability Module" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2515,7 +2409,6 @@ files = [ name = "pyobjc-framework-applicationservices" version = "9.1.1" description = "Wrappers for the framework ApplicationServices on macOS" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2537,7 +2430,6 @@ pyobjc-framework-Quartz = ">=9.1.1" name = "pyobjc-framework-cocoa" version = "9.1.1" description = "Wrappers for the Cocoa frameworks on macOS" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2557,7 +2449,6 @@ pyobjc-core = ">=9.1.1" name = "pyobjc-framework-quartz" version = "9.1.1" description = "Wrappers for the Quartz frameworks on macOS" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2578,7 +2469,6 @@ pyobjc-framework-Cocoa = ">=9.1.1" name = "pyparsing" version = "2.4.7" description = "Python parsing module" -category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2590,7 +2480,6 @@ files = [ name = "pysftp" version = "0.2.9" description = "A friendly face on SFTP" -category = "main" optional = false python-versions = "*" files = [ @@ -2604,7 +2493,6 @@ paramiko = ">=1.17" name = "pytest" version = "6.2.5" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2629,7 +2517,6 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2648,7 +2535,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-print" version = "0.3.1" description = "pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2666,7 +2552,6 @@ test = ["coverage (>=5)"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -2681,7 +2566,6 @@ six = ">=1.5" name = "python-engineio" version = "4.4.1" description = "Engine.IO server and client for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2697,7 +2581,6 @@ client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] name = "python-socketio" version = "5.8.0" description = "Socket.IO server and client for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2719,7 +2602,6 @@ client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] name = "python-xlib" version = "0.33" description = "Python X Library" -category = "main" optional = false python-versions = "*" files = [ @@ -2734,7 +2616,6 @@ six = ">=1.10.0" name = "python3-xlib" version = "0.15" description = "Python3 X Library" -category = "main" optional = false python-versions = "*" files = [ @@ -2745,7 +2626,6 @@ files = [ name = "pywin32" version = "301" description = "Python for Window Extensions" -category = "main" optional = false python-versions = "*" files = [ @@ -2765,7 +2645,6 @@ files = [ name = "pywin32-ctypes" version = "0.2.0" description = "" -category = "main" optional = false python-versions = "*" files = [ @@ -2777,7 +2656,6 @@ files = [ name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2827,7 +2705,6 @@ files = [ name = "qt-py" version = "1.3.8" description = "Python 2 & 3 compatibility wrapper around all Qt bindings - PySide, PySide2, PyQt4 and PyQt5." -category = "main" optional = false python-versions = "*" files = [ @@ -2842,7 +2719,6 @@ types-PySide2 = "*" name = "qtawesome" version = "0.7.3" description = "FontAwesome icons in PyQt and PySide applications" -category = "main" optional = false python-versions = "*" files = [ @@ -2858,7 +2734,6 @@ six = "*" name = "qtpy" version = "2.3.1" description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2876,7 +2751,6 @@ test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] name = "recommonmark" version = "0.7.1" description = "A docutils-compatibility bridge to CommonMark, enabling you to write CommonMark inside of Docutils & Sphinx projects." -category = "dev" optional = false python-versions = "*" files = [ @@ -2893,7 +2767,6 @@ sphinx = ">=1.3.1" name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2915,7 +2788,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "revitron-sphinx-theme" version = "0.7.2" description = "Revitron theme for Sphinx" -category = "dev" optional = false python-versions = "*" files = [] @@ -2937,7 +2809,6 @@ resolved_reference = "c0779c66365d9d258d93575ebaff7db9d3aee282" name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" -category = "main" optional = false python-versions = ">=3.6,<4" files = [ @@ -2952,7 +2823,6 @@ pyasn1 = ">=0.1.3" name = "secretstorage" version = "3.3.3" description = "Python bindings to FreeDesktop.org Secret Service API" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2968,7 +2838,6 @@ jeepney = ">=0.6" name = "semver" version = "2.13.0" description = "Python helper for Semantic Versioning (http://semver.org/)" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2980,7 +2849,6 @@ files = [ name = "setuptools" version = "65.7.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2997,7 +2865,6 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "shotgun-api3" version = "3.3.3" description = "Shotgun Python API" -category = "main" optional = false python-versions = "*" files = [] @@ -3013,7 +2880,6 @@ resolved_reference = "b9f066c0edbea6e0733242e18f32f75489064840" name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3025,7 +2891,6 @@ files = [ name = "slack-sdk" version = "3.21.3" description = "The Slack API Platform SDK for Python" -category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -3041,7 +2906,6 @@ testing = ["Flask (>=1,<2)", "Flask-Sockets (>=0.2,<1)", "Jinja2 (==3.0.3)", "We name = "smmap" version = "5.0.0" description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -3053,7 +2917,6 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" optional = false python-versions = "*" files = [ @@ -3065,7 +2928,6 @@ files = [ name = "speedcopy" version = "2.1.4" description = "Replacement or alternative for python copyfile() utilizing server side copy on network shares for faster copying." -category = "main" optional = false python-versions = "*" files = [ @@ -3077,7 +2939,6 @@ files = [ name = "sphinx" version = "5.3.0" description = "Python documentation generator" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -3113,7 +2974,6 @@ test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] name = "sphinx-autoapi" version = "2.1.0" description = "Sphinx API documentation generator" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3137,7 +2997,6 @@ go = ["sphinxcontrib-golangdomain"] name = "sphinxcontrib-applehelp" version = "1.0.4" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -3153,7 +3012,6 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3169,7 +3027,6 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -3185,7 +3042,6 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3200,7 +3056,6 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-napoleon" version = "0.7" description = "Sphinx \"napoleon\" extension." -category = "dev" optional = false python-versions = "*" files = [ @@ -3216,7 +3071,6 @@ six = ">=1.5.2" name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3232,7 +3086,6 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3248,7 +3101,6 @@ test = ["pytest"] name = "stone" version = "3.3.1" description = "Stone is an interface description language (IDL) for APIs." -category = "main" optional = false python-versions = "*" files = [ @@ -3265,7 +3117,6 @@ six = ">=1.12.0" name = "termcolor" version = "1.1.0" description = "ANSII Color formatting for output in terminal." -category = "main" optional = false python-versions = "*" files = [ @@ -3276,7 +3127,6 @@ files = [ name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3288,7 +3138,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3300,7 +3149,6 @@ files = [ name = "tomlkit" version = "0.11.8" description = "Style preserving TOML library" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3312,7 +3160,6 @@ files = [ name = "types-pyside2" version = "5.15.2.1.5" description = "The most accurate stubs for PySide2" -category = "main" optional = false python-versions = "*" files = [ @@ -3323,7 +3170,6 @@ files = [ name = "typing-extensions" version = "4.6.2" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3335,7 +3181,6 @@ files = [ name = "uc-micro-py" version = "1.0.2" description = "Micro subset of unicode data files for linkify-it-py projects." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3350,7 +3195,6 @@ test = ["coverage", "pytest", "pytest-cov"] name = "unidecode" version = "1.2.0" description = "ASCII transliterations of Unicode text" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3362,7 +3206,6 @@ files = [ name = "uritemplate" version = "3.0.1" description = "URI templates" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3374,7 +3217,6 @@ files = [ name = "urllib3" version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -3391,7 +3233,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "virtualenv" version = "20.23.0" description = "Virtual Python Environment builder" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3412,7 +3253,6 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "main" optional = false python-versions = "*" files = [ @@ -3424,7 +3264,6 @@ files = [ name = "websocket-client" version = "0.59.0" description = "WebSocket client for Python with low level API options" -category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3439,7 +3278,6 @@ six = "*" name = "wheel" version = "0.40.0" description = "A built-package format for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3454,7 +3292,6 @@ test = ["pytest (>=6.0.0)"] name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -3539,7 +3376,6 @@ files = [ name = "wsrpc-aiohttp" version = "3.2.0" description = "WSRPC is the RPC over WebSocket for aiohttp" -category = "main" optional = false python-versions = ">3.5.*, <4" files = [ @@ -3560,7 +3396,6 @@ ujson = ["ujson"] name = "yarl" version = "1.9.2" description = "Yet another URL library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3648,7 +3483,6 @@ multidict = ">=4.0" name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3665,5 +3499,5 @@ docs = [] [metadata] lock-version = "2.0" -python-versions = ">=3.9.1,<3.10" -content-hash = "d2b8da22dcd11e0b03f19b9b79e51f205156c5ce75e41cc0225392e9afd8803b" +python-versions = "~3.9" +content-hash = "bc3e256094db6e33894840bb6a5adda4473d3736b852433ad8d5bd478c7e0c1c" From 817ef16840467b55c0832d74696d5ba29ad20929 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:04:08 +0200 Subject: [PATCH 096/103] lower version of click to 7.1.2 to support older python versions (#5629) --- poetry.lock | 11 ++++------- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2b9fab4bc4..d074a0c3d9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -560,18 +560,15 @@ files = [ [[package]] name = "click" -version = "8.1.3" +version = "7.1.2" description = "Composable command line interface toolkit" optional = false -python-versions = ">=3.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, ] -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "clique" version = "1.6.1" diff --git a/pyproject.toml b/pyproject.toml index e2d35f3c6d..68d31cf4ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ appdirs = { git = "https://github.com/ActiveState/appdirs.git", branch = "master blessed = "^1.17" # openpype terminal formatting coolname = "*" clique = "1.6.*" -Click = "^8" +Click = "7.1.2" dnspython = "^2.1.0" ftrack-python-api = "^2.3.3" arrow = "^0.17" From 87d8ff66bbb90dd81a93266ba16cf56273d93613 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Tue, 19 Sep 2023 15:47:43 +0000 Subject: [PATCH 097/103] [Automated] Release --- CHANGELOG.md | 122 ++++++++++++++++++++++++++++++++++++++++++++ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 935e7dbc4c..9001e9fec5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,128 @@ # Changelog +## [3.16.8](https://github.com/ynput/OpenPype/tree/3.16.8) + + +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.16.7...3.16.8) + +### **🚀 Enhancements** + + +
+Chore: Remove schema from OpenPype root #5355 + +Remove unused schema directory in root of repository which was moved inside openpype/pipeline/schema. + + +___ + +
+ + +
+Igniter: Allow custom Qt scale factor rounding policy #5554 + +Do not force `PassThrough` rounding policy if different policy is defined via env variable. + + +___ + +
+ +### **🐛 Bug fixes** + + +
+Chore: Lower urllib3 to support older OpenSSL #5538 + +Lowered `urllib3` to `1.26.16` to support older OpenSSL. + + +___ + +
+ + +
+Chore: Do not try to add schema to zip files #5557 + +Do not add `schema` folder to zip file. This fixes issue cause by https://github.com/ynput/OpenPype/pull/5355 . + + +___ + +
+ + +
+Chore: Lower click dependency version #5629 + +Lower click version to support older versions of python. + + +___ + +
+ +### **Merged pull requests** + + +
+Bump certifi from 2023.5.7 to 2023.7.22 #5351 + +Bumps [certifi](https://github.com/certifi/python-certifi) from 2023.5.7 to 2023.7.22. +
+Commits + +
+
+ + +[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=certifi&package-manager=pip&previous-version=2023.5.7&new-version=2023.7.22)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) + +You can trigger a rebase of this PR by commenting `@dependabot rebase`. + +[//]: # (dependabot-automerge-start) +[//]: # (dependabot-automerge-end) + +--- + +
+Dependabot commands and options +
+ +You can trigger Dependabot actions by commenting on this PR: +- `@dependabot rebase` will rebase this PR +- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it +- `@dependabot merge` will merge this PR after your CI passes on it +- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it +- `@dependabot cancel merge` will cancel a previously requested merge and block automerging +- `@dependabot reopen` will reopen this PR if it is closed +- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually +- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) +- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) +You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts). + +
+ +> **Note** +> Automatic rebases have been disabled on this pull request as it has been open for over 30 days. + +___ + +
+ + + + ## [3.16.7](https://github.com/ynput/OpenPype/tree/3.16.7) diff --git a/openpype/version.py b/openpype/version.py index c593f0f71f..0578bb8780 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.16.7" +__version__ = "3.16.8" diff --git a/pyproject.toml b/pyproject.toml index b394a895e3..c5d5e87f49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.16.7" # OpenPype +version = "3.16.8" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 5bf4b826ac960103f121f094506100e993507bef Mon Sep 17 00:00:00 2001 From: Petr Dvorak Date: Tue, 19 Sep 2023 17:56:06 +0200 Subject: [PATCH 098/103] update release --- CHANGELOG.md | 4 ++-- openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9001e9fec5..4bcf66a210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,10 @@ # Changelog -## [3.16.8](https://github.com/ynput/OpenPype/tree/3.16.8) +## [3.17.0](https://github.com/ynput/OpenPype/tree/3.17.0) -[Full Changelog](https://github.com/ynput/OpenPype/compare/3.16.7...3.16.8) +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.16.7...3.17.0) ### **🚀 Enhancements** diff --git a/openpype/version.py b/openpype/version.py index 0578bb8780..281e756967 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.16.8" +__version__ = "3.17.0" diff --git a/pyproject.toml b/pyproject.toml index 233cf73db8..d0b1ecf589 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.16.8" # OpenPype +version = "3.17.0" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 77600e624c31697f515ac37d3d0834253d0951bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 Sep 2023 15:48:46 +0000 Subject: [PATCH 099/103] 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 9159d3fe4a..be515983ca 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.16.8 - 3.16.7 - 3.16.7-nightly.2 - 3.16.7-nightly.1 @@ -134,7 +135,6 @@ body: - 3.14.10-nightly.3 - 3.14.10-nightly.2 - 3.14.10-nightly.1 - - 3.14.9 validations: required: true - type: dropdown From dc5c730cba6119342600dcbe6a5a13d6d1c4b569 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 Sep 2023 16:01:55 +0000 Subject: [PATCH 100/103] 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 be515983ca..0762eb2f20 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,7 +35,7 @@ body: label: Version description: What version are you running? Look to OpenPype Tray options: - - 3.16.8 + - 3.17.0 - 3.16.7 - 3.16.7-nightly.2 - 3.16.7-nightly.1 From 7195479080639489b65a2715b3fba74414dc8815 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 20 Sep 2023 03:24:46 +0000 Subject: [PATCH 101/103] [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 281e756967..483b70436a 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.17.0" +__version__ = "3.17.1-nightly.1" From 41845651b2aaf701b3a7d27c0091a23948c3c2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:38:35 +0200 Subject: [PATCH 102/103] Update setup.cfg Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 216bae848f..ead9b25164 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ omit = /tests directory = ./coverage [tool:pytest] -norecursedirs = repos/* openpype/modules/ftrack/* +norecursedirs = openpype/modules/ftrack/* [isort] line_length = 79 From 23e9f5e504c482bc13268d16190378142b5ca936 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:26:33 +0200 Subject: [PATCH 103/103] TVPaint: Fix review family extraction (#5637) * mark review family representation for review * implemented 'get_publish_instance_families' in publish lib * use 'get_publish_instance_families' in tvpaint extract sequence --- .../plugins/publish/extract_sequence.py | 8 +++++-- openpype/pipeline/publish/__init__.py | 2 ++ openpype/pipeline/publish/lib.py | 24 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py index a13a91de46..fd568b2826 100644 --- a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py +++ b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py @@ -6,7 +6,10 @@ from PIL import Image import pyblish.api -from openpype.pipeline.publish import KnownPublishError +from openpype.pipeline.publish import ( + KnownPublishError, + get_publish_instance_families, +) from openpype.hosts.tvpaint.api.lib import ( execute_george, execute_george_through_file, @@ -140,8 +143,9 @@ class ExtractSequence(pyblish.api.Extractor): ) # Fill tags and new families from project settings + instance_families = get_publish_instance_families(instance) tags = [] - if "review" in instance.data["families"]: + if "review" in instance_families: tags.append("review") # Sequence of one frame diff --git a/openpype/pipeline/publish/__init__.py b/openpype/pipeline/publish/__init__.py index 0c57915c05..3a82d6f565 100644 --- a/openpype/pipeline/publish/__init__.py +++ b/openpype/pipeline/publish/__init__.py @@ -40,6 +40,7 @@ from .lib import ( apply_plugin_settings_automatically, get_plugin_settings, get_publish_instance_label, + get_publish_instance_families, ) from .abstract_expected_files import ExpectedFiles @@ -87,6 +88,7 @@ __all__ = ( "apply_plugin_settings_automatically", "get_plugin_settings", "get_publish_instance_label", + "get_publish_instance_families", "ExpectedFiles", diff --git a/openpype/pipeline/publish/lib.py b/openpype/pipeline/publish/lib.py index 1ae6ea43b2..4d9443f635 100644 --- a/openpype/pipeline/publish/lib.py +++ b/openpype/pipeline/publish/lib.py @@ -1002,3 +1002,27 @@ def get_publish_instance_label(instance): or instance.data.get("name") or str(instance) ) + + +def get_publish_instance_families(instance): + """Get all families of the instance. + + Look for families under 'family' and 'families' keys in instance data. + Value of 'family' is used as first family and then all other families + in random order. + + Args: + pyblish.api.Instance: Instance to get families from. + + Returns: + list[str]: List of families. + """ + + family = instance.data.get("family") + families = set(instance.data.get("families") or []) + output = [] + if family: + output.append(family) + families.discard(family) + output.extend(families) + return output