From 45bb933e801d703f527bc5813c649f29b3c5312e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 25 Jan 2024 17:09:44 +0800 Subject: [PATCH 01/30] implement validator for model name in 3dsmax --- openpype/hosts/max/api/action.py | 39 ++++++++ .../plugins/publish/validate_model_name.py | 93 +++++++++++++++++++ .../defaults/project_settings/max.json | 6 ++ .../schemas/schema_max_publish.json | 24 +++++ .../max/server/settings/publishers.py | 20 ++++ server_addon/max/server/version.py | 2 +- 6 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/max/api/action.py create mode 100644 openpype/hosts/max/plugins/publish/validate_model_name.py diff --git a/openpype/hosts/max/api/action.py b/openpype/hosts/max/api/action.py new file mode 100644 index 0000000000..506847652b --- /dev/null +++ b/openpype/hosts/max/api/action.py @@ -0,0 +1,39 @@ +from pymxs import runtime as rt + +import pyblish.api + +from openpype.pipeline.publish import get_errored_instances_from_context + + +class SelectInvalidAction(pyblish.api.Action): + """Select invalid objects in Blender when a publish plug-in failed.""" + label = "Select Invalid" + on = "failed" + icon = "search" + + def process(self, context, plugin): + errored_instances = get_errored_instances_from_context(context, + plugin=plugin) + + # Get the invalid nodes for the plug-ins + self.log.info("Finding invalid nodes...") + invalid = list() + for instance in errored_instances: + invalid_nodes = plugin.get_invalid(instance) + if invalid_nodes: + if isinstance(invalid_nodes, (list, tuple)): + invalid.extend(invalid_nodes) + else: + self.log.warning( + "Failed plug-in doesn't have any selectable objects." + ) + + if not invalid: + self.log.info("No invalid nodes found.") + return + invalid_names = [obj.name for obj in invalid] + self.log.info( + "Selecting invalid objects: %s", ", ".join(invalid_names) + ) + + rt.Select(invalid) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py new file mode 100644 index 0000000000..3da9c9e0eb --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +"""Validate model nodes names.""" +import re + +import pyblish.api +from pymxs import runtime as rt + +from openpype.hosts.max.api.action import SelectInvalidAction + +from openpype.pipeline.publish import ( + OptionalPyblishPluginMixin, + PublishValidationError, + ValidateContentsOrder) + + +class ValidateModelName(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): + """Validate name of model + + starts with (somename)_###_(materialID)_GEO + + """ + optional = True + order = ValidateContentsOrder + hosts = ["max"] + families = ["model"] + label = "Validate Model Name" + actions = [SelectInvalidAction] + regex = "" + + @classmethod + def get_invalid(cls, instance): + invalid = [] + #TODO: validation regex for validation + model_names = [model.name for model in instance.data.get("members")] + cls.log.debug(model_names) + if not model_names: + cls.log.error("No Model found in the OP Data.") + invalid.append(model_names) + for name in model_names: + invalid_model_name = cls.get_invalid_model_name(instance, name) + invalid.extend(invalid_model_name) + + return invalid + + @classmethod + def get_invalid_model_name(cls, instance, name): + invalid = [] + + regex = cls.regex + reg = re.compile(regex) + matched_name = reg.match(name) + project_name = instance.context.data["projectName"] + current_asset_name = instance.context.data["asset"] + if matched_name is None: + cls.log.error("invalid model name on: {}".format(name)) + cls.log.error("name doesn't match regex {}".format(regex)) + invalid.append((rt.getNodeByName(name), + "Model name doesn't match regex")) + else: + if "asset" in reg.groupindex: + if matched_name.group("asset") != current_asset_name: + cls.log.error( + "Invalid asset name of the model {}.".format(name) + ) + invalid.append((rt.getNodeByName(name), + "Model with invalid asset name")) + if "subset" in reg.groupindex: + if matched_name.group("subset") != instance.name: + cls.log.error( + "Invalid subset name of the model {}.".format(name) + ) + invalid.append((rt.getNodeByName(name), + "Model with invalid subset name")) + if "project" in reg.groupindex: + if matched_name.group("project") != project_name: + cls.log.error( + "Invalid project name of the model {}.".format(name) + ) + invalid.append((rt.getNodeByName(name), + "Model with invalid project name")) + return invalid + + def process(self, instance): + if not self.is_active(instance.data): + self.log.debug("Skipping Validate Frame Range...") + return + + invalid = self.get_invalid(instance) + + if invalid: + raise PublishValidationError( + "Model naming is invalid. See the log.") diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index d1610610dc..f719e7a156 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -56,6 +56,12 @@ "enabled": false, "attributes": {} }, + "ValidateModelName": { + "enabled": true, + "optional": true, + "active": false, + "regex": "(?P.*)_(GEO)" + }, "ValidateLoadedPlugin": { "enabled": false, "optional": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json index b4d85bda98..1e42b017ff 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_max_publish.json @@ -48,6 +48,30 @@ } ] }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateModelName", + "label": "Validate Model Name", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "text", + "key": "regex", + "label": "validation regex" + } + ] + }, { "type": "dict", "collapsible": true, diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index d40d85a99b..9b11946195 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -38,6 +38,20 @@ class FamilyMappingItemModel(BaseSettingsModel): ) +class ValidateModelName(BaseSettingsModel): + enabled: bool = Field(title="Enabled") + optional: bool = Field(title="Optional") + active: bool = Field(title="Active") + regex: str = Field( + "(?P.*)_(GEO)", + title="Validation regex", + description=( + "Regex for validating model name. You can use named " + " capturing groups:(?P.*) for Asset name" + ) + ) + + class ValidateLoadedPluginModel(BaseSettingsModel): enabled: bool = Field(title="Enabled") optional: bool = Field(title="Optional") @@ -101,6 +115,12 @@ DEFAULT_PUBLISH_SETTINGS = { "enabled": False, "attributes": "{}" }, + "ValidateModelName": { + "enabled": True, + "optional": True, + "active": False, + "regex": "(?P.*)_(GEO)" + }, "ValidateLoadedPlugin": { "enabled": False, "optional": True, diff --git a/server_addon/max/server/version.py b/server_addon/max/server/version.py index bbab0242f6..1276d0254f 100644 --- a/server_addon/max/server/version.py +++ b/server_addon/max/server/version.py @@ -1 +1 @@ -__version__ = "0.1.4" +__version__ = "0.1.5" From d387dca0272c9be2a80beb52ac8272cabb10f426 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 26 Jan 2024 10:44:13 +0000 Subject: [PATCH 02/30] Use duration from streams as its more precise --- openpype/plugins/publish/extract_thumbnail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index 10eb261482..37f7ea7737 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -445,7 +445,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # Set video input attributes max_int = str(2147483647) video_data = get_ffprobe_data(video_file_path, logger=self.log) - duration = float(video_data["format"]["duration"]) + duration = float(video_data["streams"][0]["duration"]) cmd_args = [ "-y", From e6818f94f5fead64b6ff8767462064fef8e10a41 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Mon, 29 Jan 2024 09:17:07 +0000 Subject: [PATCH 03/30] Illicit suggestion --- openpype/plugins/publish/extract_thumbnail.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index 37f7ea7737..8a1e9fd12d 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -445,7 +445,11 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # Set video input attributes max_int = str(2147483647) video_data = get_ffprobe_data(video_file_path, logger=self.log) - duration = float(video_data["streams"][0]["duration"]) + duration = max( + float(stream.get("duration", 0)) + for stream in video_data["streams"] + if stream.get("codec_type") == "video" + ) cmd_args = [ "-y", From 1d83c6aaa8adcb77ba9b5395cceae064e4aa8e0a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 29 Jan 2024 17:19:04 +0800 Subject: [PATCH 04/30] add validate model name settings for ayon --- server_addon/max/server/settings/publishers.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index 672f422fce..fcd034bcf0 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -38,11 +38,11 @@ class FamilyMappingItemModel(BaseSettingsModel): ) -class ValidateModelName(BaseSettingsModel): - enabled: bool = Field(title="Enabled") - optional: bool = Field(title="Optional") - active: bool = Field(title="Active") - regex: str = Field( +class ValidateModelNameModel(BaseSettingsModel): + enabled: bool = SettingsField(title="Enabled") + optional: bool = SettingsField(title="Optional") + active: bool = SettingsField(title="Active") + regex: str = SettingsField( "(?P.*)_(GEO)", title="Validation regex", description=( @@ -82,6 +82,10 @@ class PublishersModel(BaseSettingsModel): default_factory=ValidateLoadedPluginModel, title="Validate Loaded Plugin" ) + ValidateModelName: ValidateModelNameModel = SettingsField( + default_factory=ValidateModelNameModel, + title="Validate Model Name" + ) ExtractModelObj: BasicValidateModel = SettingsField( default_factory=BasicValidateModel, title="Extract OBJ", From 43aadb215b631d5ed6f149d945ba020652425046 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 29 Jan 2024 17:20:08 +0800 Subject: [PATCH 05/30] resolve hound --- openpype/hosts/max/plugins/publish/validate_model_name.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index 3da9c9e0eb..c85b4729c5 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -31,7 +31,6 @@ class ValidateModelName(pyblish.api.InstancePlugin, @classmethod def get_invalid(cls, instance): invalid = [] - #TODO: validation regex for validation model_names = [model.name for model in instance.data.get("members")] cls.log.debug(model_names) if not model_names: From b822dd0e8d762c6641f1637fad4f9220bdfc7480 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 29 Jan 2024 17:27:22 +0800 Subject: [PATCH 06/30] add docstring --- openpype/hosts/max/plugins/publish/validate_model_name.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index c85b4729c5..9603c45150 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -15,9 +15,11 @@ from openpype.pipeline.publish import ( class ValidateModelName(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): - """Validate name of model + """Validate Model Name + Validation regex is (?P.*)_(GEO) by default. + e.g. (subset_name)_GEO should be your model name - starts with (somename)_###_(materialID)_GEO + starts with (somename)_GEO """ optional = True @@ -45,7 +47,6 @@ class ValidateModelName(pyblish.api.InstancePlugin, @classmethod def get_invalid_model_name(cls, instance, name): invalid = [] - regex = cls.regex reg = re.compile(regex) matched_name = reg.match(name) From 5e8af09c4b116476cc80d5ca7ba22f969ae534e7 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 29 Jan 2024 17:53:35 +0800 Subject: [PATCH 07/30] update regex name --- openpype/hosts/max/plugins/publish/validate_model_name.py | 2 +- openpype/settings/defaults/project_settings/max.json | 2 +- server_addon/max/server/settings/publishers.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index 9603c45150..a264221372 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -83,7 +83,7 @@ class ValidateModelName(pyblish.api.InstancePlugin, def process(self, instance): if not self.is_active(instance.data): - self.log.debug("Skipping Validate Frame Range...") + self.log.debug("Skipping Validate Model Name...") return invalid = self.get_invalid(instance) diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index f719e7a156..e8fb2d31c4 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -60,7 +60,7 @@ "enabled": true, "optional": true, "active": false, - "regex": "(?P.*)_(GEO)" + "regex": "(.*)_(?P.*)_(GEO)" }, "ValidateLoadedPlugin": { "enabled": false, diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index fcd034bcf0..761f4c54f1 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -43,7 +43,7 @@ class ValidateModelNameModel(BaseSettingsModel): optional: bool = SettingsField(title="Optional") active: bool = SettingsField(title="Active") regex: str = SettingsField( - "(?P.*)_(GEO)", + "(.*)_(?P.*)_(GEO)", title="Validation regex", description=( "Regex for validating model name. You can use named " @@ -123,7 +123,7 @@ DEFAULT_PUBLISH_SETTINGS = { "enabled": True, "optional": True, "active": False, - "regex": "(?P.*)_(GEO)" + "regex": "*_(?P.*)_(GEO)" }, "ValidateLoadedPlugin": { "enabled": False, From 3f8830e27d9c7f4002985ebcf05f7fe395fc3e17 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 29 Jan 2024 10:13:18 +0000 Subject: [PATCH 08/30] Update openpype/plugins/publish/extract_thumbnail.py --- openpype/plugins/publish/extract_thumbnail.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index 8a1e9fd12d..2e272b061b 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -445,6 +445,10 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # Set video input attributes max_int = str(2147483647) video_data = get_ffprobe_data(video_file_path, logger=self.log) + # Use duration of the individual streams since it is returned with + # higher decimal precision than 'format.duration'. We need this + # more precise value for calculating the correct amount of frames + # for higher FPS ranges or decimal ranges, e.g. 29.97 FPS duration = max( float(stream.get("duration", 0)) for stream in video_data["streams"] From 3807172faed3addc22790c6831065d7424e08035 Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Mon, 29 Jan 2024 10:13:40 +0000 Subject: [PATCH 09/30] Update openpype/plugins/publish/extract_thumbnail.py --- openpype/plugins/publish/extract_thumbnail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index 2e272b061b..cbeada6bac 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -448,7 +448,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # Use duration of the individual streams since it is returned with # higher decimal precision than 'format.duration'. We need this # more precise value for calculating the correct amount of frames - # for higher FPS ranges or decimal ranges, e.g. 29.97 FPS + # for higher FPS ranges or decimal ranges, e.g. 29.97 FPS duration = max( float(stream.get("duration", 0)) for stream in video_data["streams"] From 6b9da9b1e83a1be30197d00d4aae198050590d33 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 2 Feb 2024 16:14:08 +0800 Subject: [PATCH 10/30] update docstring --- .../max/plugins/publish/validate_model_name.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index a264221372..b0e5677592 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -16,10 +16,17 @@ from openpype.pipeline.publish import ( class ValidateModelName(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): """Validate Model Name - Validation regex is (?P.*)_(GEO) by default. - e.g. (subset_name)_GEO should be your model name + Validation regex is (.*)_(?P.*)_(GEO) by default. + e.g. {SOME_RANDOM_NAME}_{YOUR_SUBSET_NAME}_GEO should be your + default model name - starts with (somename)_GEO + The regex of (?P.*) can be replaced by (?P.*) + and (?P.*). + e.g. + - (.*)_(?P.*)_(GEO) check if your model name is + {SOME_RANDOM_NAME}_{CURRENT_ASSET_NAME}_GEO + - (.*)_(?P.*)_(GEO) check if your model name is + {SOME_RANDOM_NAME}_{CURRENT_PROJECT_NAME}_GEO """ optional = True From 12f78b17668c8f5034c60f8ba6921a5aa507c015 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 5 Feb 2024 20:12:22 +0800 Subject: [PATCH 11/30] update regex in ayon settings --- server_addon/max/server/settings/publishers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index 761f4c54f1..05d084aac5 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -123,7 +123,7 @@ DEFAULT_PUBLISH_SETTINGS = { "enabled": True, "optional": True, "active": False, - "regex": "*_(?P.*)_(GEO)" + "regex": "(.*)_(?P.*)_(GEO)" }, "ValidateLoadedPlugin": { "enabled": False, From 09342f56338456d3a2e8245a7738d0d23c6da281 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 5 Feb 2024 23:29:18 +0800 Subject: [PATCH 12/30] fix action.py --- openpype/hosts/max/api/action.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/api/action.py b/openpype/hosts/max/api/action.py index 506847652b..818d4db6e5 100644 --- a/openpype/hosts/max/api/action.py +++ b/openpype/hosts/max/api/action.py @@ -31,9 +31,10 @@ class SelectInvalidAction(pyblish.api.Action): if not invalid: self.log.info("No invalid nodes found.") return - invalid_names = [obj.name for obj in invalid] + self.log.debug(f"invalid{invalid}") + invalid_names = [obj for obj, _ in invalid] self.log.info( - "Selecting invalid objects: %s", ", ".join(invalid_names) + f"Selecting invalid objects: {invalid_names}" ) - rt.Select(invalid) + rt.Select(invalid_names) From 1a63065c13ef70762e994519aaec1d4294ecd81c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 5 Feb 2024 23:34:30 +0800 Subject: [PATCH 13/30] fix action.py --- openpype/hosts/max/api/action.py | 7 +++---- .../hosts/max/plugins/publish/validate_model_name.py | 12 ++++-------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/max/api/action.py b/openpype/hosts/max/api/action.py index 818d4db6e5..506847652b 100644 --- a/openpype/hosts/max/api/action.py +++ b/openpype/hosts/max/api/action.py @@ -31,10 +31,9 @@ class SelectInvalidAction(pyblish.api.Action): if not invalid: self.log.info("No invalid nodes found.") return - self.log.debug(f"invalid{invalid}") - invalid_names = [obj for obj, _ in invalid] + invalid_names = [obj.name for obj in invalid] self.log.info( - f"Selecting invalid objects: {invalid_names}" + "Selecting invalid objects: %s", ", ".join(invalid_names) ) - rt.Select(invalid_names) + rt.Select(invalid) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index b0e5677592..3cd7265077 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -62,30 +62,26 @@ class ValidateModelName(pyblish.api.InstancePlugin, if matched_name is None: cls.log.error("invalid model name on: {}".format(name)) cls.log.error("name doesn't match regex {}".format(regex)) - invalid.append((rt.getNodeByName(name), - "Model name doesn't match regex")) + invalid.append((name,"Model name doesn't match regex")) else: if "asset" in reg.groupindex: if matched_name.group("asset") != current_asset_name: cls.log.error( "Invalid asset name of the model {}.".format(name) ) - invalid.append((rt.getNodeByName(name), - "Model with invalid asset name")) + invalid.append((name, "Model with invalid asset name")) if "subset" in reg.groupindex: if matched_name.group("subset") != instance.name: cls.log.error( "Invalid subset name of the model {}.".format(name) ) - invalid.append((rt.getNodeByName(name), - "Model with invalid subset name")) + invalid.append((name, "Model with invalid subset name")) if "project" in reg.groupindex: if matched_name.group("project") != project_name: cls.log.error( "Invalid project name of the model {}.".format(name) ) - invalid.append((rt.getNodeByName(name), - "Model with invalid project name")) + invalid.append((name, "Model with invalid project name")) return invalid def process(self, instance): From bfd952007feb1f37eec2924d510637cfbee01c60 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 5 Feb 2024 23:35:41 +0800 Subject: [PATCH 14/30] hound --- openpype/hosts/max/plugins/publish/validate_model_name.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index 3cd7265077..a36947931c 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -3,7 +3,6 @@ import re import pyblish.api -from pymxs import runtime as rt from openpype.hosts.max.api.action import SelectInvalidAction @@ -62,7 +61,7 @@ class ValidateModelName(pyblish.api.InstancePlugin, if matched_name is None: cls.log.error("invalid model name on: {}".format(name)) cls.log.error("name doesn't match regex {}".format(regex)) - invalid.append((name,"Model name doesn't match regex")) + invalid.append((name, "Model name doesn't match regex")) else: if "asset" in reg.groupindex: if matched_name.group("asset") != current_asset_name: From 05b97437b8f28bb43dc6ed303cbb6049f42c1316 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 8 Feb 2024 19:49:38 +0800 Subject: [PATCH 15/30] fix Libor's mentioned bug on action.py --- openpype/hosts/max/api/action.py | 5 ++++- .../hosts/max/plugins/publish/validate_model_name.py | 11 +++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/max/api/action.py b/openpype/hosts/max/api/action.py index 506847652b..c3c1957af1 100644 --- a/openpype/hosts/max/api/action.py +++ b/openpype/hosts/max/api/action.py @@ -31,7 +31,10 @@ class SelectInvalidAction(pyblish.api.Action): if not invalid: self.log.info("No invalid nodes found.") return - invalid_names = [obj.name for obj in invalid] + invalid_names = [obj.name for obj in invalid if isinstance(obj, str)] + if not invalid_names: + invalid_names = [obj.name for obj, _ in invalid] + invalid = [obj for obj, _ in invalid] self.log.info( "Selecting invalid objects: %s", ", ".join(invalid_names) ) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index a36947931c..bf4f29fa97 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -3,6 +3,7 @@ import re import pyblish.api +from pymxs import runtime as rt from openpype.hosts.max.api.action import SelectInvalidAction @@ -61,26 +62,28 @@ class ValidateModelName(pyblish.api.InstancePlugin, if matched_name is None: cls.log.error("invalid model name on: {}".format(name)) cls.log.error("name doesn't match regex {}".format(regex)) - invalid.append((name, "Model name doesn't match regex")) + invalid.append((rt.getNodeByName(name), + "Model name doesn't match regex")) else: if "asset" in reg.groupindex: if matched_name.group("asset") != current_asset_name: cls.log.error( "Invalid asset name of the model {}.".format(name) ) - invalid.append((name, "Model with invalid asset name")) + invalid.append((rt.getNodeByName(name), + "Model with invalid asset name")) if "subset" in reg.groupindex: if matched_name.group("subset") != instance.name: cls.log.error( "Invalid subset name of the model {}.".format(name) ) - invalid.append((name, "Model with invalid subset name")) + invalid.append((rt.getNodeByName(name), "Model with invalid subset name")) if "project" in reg.groupindex: if matched_name.group("project") != project_name: cls.log.error( "Invalid project name of the model {}.".format(name) ) - invalid.append((name, "Model with invalid project name")) + invalid.append((rt.getNodeByName(name), "Model with invalid project name")) return invalid def process(self, instance): From c9db6449dac57cc0a60210724bac8061c9d88da1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 8 Feb 2024 19:50:48 +0800 Subject: [PATCH 16/30] hound shut --- openpype/hosts/max/plugins/publish/validate_model_name.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_model_name.py b/openpype/hosts/max/plugins/publish/validate_model_name.py index bf4f29fa97..455c12a85b 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_name.py +++ b/openpype/hosts/max/plugins/publish/validate_model_name.py @@ -77,13 +77,15 @@ class ValidateModelName(pyblish.api.InstancePlugin, cls.log.error( "Invalid subset name of the model {}.".format(name) ) - invalid.append((rt.getNodeByName(name), "Model with invalid subset name")) + invalid.append((rt.getNodeByName(name), + "Model with invalid subset name")) if "project" in reg.groupindex: if matched_name.group("project") != project_name: cls.log.error( "Invalid project name of the model {}.".format(name) ) - invalid.append((rt.getNodeByName(name), "Model with invalid project name")) + invalid.append((rt.getNodeByName(name), + "Model with invalid project name")) return invalid def process(self, instance): From 0aea2ae39f4f947716c7ef69f49bda5dd13ad5c1 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 9 Feb 2024 08:11:11 +0000 Subject: [PATCH 17/30] Add submodule --- client/ayon_core/hosts/unreal/integration | 1 + 1 file changed, 1 insertion(+) create mode 160000 client/ayon_core/hosts/unreal/integration diff --git a/client/ayon_core/hosts/unreal/integration b/client/ayon_core/hosts/unreal/integration new file mode 160000 index 0000000000..6d2793170e --- /dev/null +++ b/client/ayon_core/hosts/unreal/integration @@ -0,0 +1 @@ +Subproject commit 6d2793170ed57187842f683a943593973abcc337 From 4a85b2ec45a05f066758b6be4e17588cdfd51598 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 21 Feb 2024 21:01:12 +0800 Subject: [PATCH 18/30] bug fix the action.py --- client/ayon_core/hosts/max/api/action.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/max/api/action.py b/client/ayon_core/hosts/max/api/action.py index 58834d0172..bed72bc493 100644 --- a/client/ayon_core/hosts/max/api/action.py +++ b/client/ayon_core/hosts/max/api/action.py @@ -31,7 +31,7 @@ class SelectInvalidAction(pyblish.api.Action): if not invalid: self.log.info("No invalid nodes found.") return - invalid_names = [obj.name for obj in invalid if isinstance(obj, str)] + invalid_names = [obj.name for obj in invalid if not isinstance(obj, tuple)] if not invalid_names: invalid_names = [obj.name for obj, _ in invalid] invalid = [obj for obj, _ in invalid] From c25161d454ca05dc21abff0eacf885c2e6cddbd8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 22 Feb 2024 18:26:54 +0800 Subject: [PATCH 19/30] coverting asset to folderPath --- .../ayon_core/hosts/max/plugins/publish/validate_model_name.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py b/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py index 7859889561..87a9132989 100644 --- a/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py +++ b/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py @@ -58,7 +58,7 @@ class ValidateModelName(pyblish.api.InstancePlugin, reg = re.compile(regex) matched_name = reg.match(name) project_name = instance.context.data["projectName"] - current_asset_name = instance.context.data["asset"] + current_asset_name = instance.context.data["folderPath"] if matched_name is None: cls.log.error("invalid model name on: {}".format(name)) cls.log.error("name doesn't match regex {}".format(regex)) From 344e244a993a3082b8836afdb87f5883e63ff0e8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 26 Feb 2024 18:04:40 +0800 Subject: [PATCH 20/30] validate no animation for model family in Max --- .../plugins/publish/validate_no_animation.py | 67 +++++++++++++++++++ .../max/server/settings/publishers.py | 9 +++ server_addon/max/server/version.py | 2 +- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py new file mode 100644 index 0000000000..9f859a1b28 --- /dev/null +++ b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from pymxs import runtime as rt +from ayon_core.pipeline import ( + PublishValidationError, + OptionalPyblishPluginMixin +) +from ayon_core.hosts.max.api.action import SelectInvalidAction + + +class ValidateNoAnimation(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): + """Validates No Animation + + Ensure no keyframes on nodes in the Instance + """ + + order = pyblish.api.ValidatorOrder + families = ["model"] + hosts = ["max"] + optional = True + label = "Validate No Animation" + actions = [SelectInvalidAction] + + def process(self, instance): + if not self.is_active(instance.data): + return + invalid = self.get_invalid(instance) + if invalid: + bullet_point_invalid_statement = "\n".join( + "- {}: {}".format(obj, message) + for obj, message in invalid + ) + raise PublishValidationError( + "Keyframes found on:\n\n{0}".format( + bullet_point_invalid_statement) + , + title="Keyframes on model" + ) + + @staticmethod + def get_invalid(instance): + invalid = [] + selected_objects = instance.data["members"] + for sel in selected_objects: + sel_pos_ctl = rt.getPropertyController( + sel.controller, 'Position') + ctl_count = (sel_pos_ctl.keys).count + if len(ctl_count) > 0: + invalid.append( + (sel), f"Object Position(s) has {ctl_count} keyframe(s)") + sel_rot_ctl = rt.getPropertyController( + sel.controller, "Rotation" + ) + ctl_count = (sel_rot_ctl.keys).count + if len(ctl_count) > 0: + invalid.append( + (sel), f"Object Rotation(s) has {ctl_count} keyframe(s)") + sel_scale_ctl = rt.getPropertyController( + sel.controller, "Scale" + ) + ctl_count = (sel_scale_ctl.keys).count + if len(ctl_count) > 0: + invalid.append( + (sel), f"Object Rotation(s) has {ctl_count} keyframe(s)") + + return invalid diff --git a/server_addon/max/server/settings/publishers.py b/server_addon/max/server/settings/publishers.py index 5e28c1b467..8f9f1009f4 100644 --- a/server_addon/max/server/settings/publishers.py +++ b/server_addon/max/server/settings/publishers.py @@ -82,6 +82,10 @@ class PublishersModel(BaseSettingsModel): "the system automatically skips checking it" ) ) + ValidateNoAnimation: BasicValidateModel = SettingsField( + default_factory=BasicValidateModel, + title="Validate No Animation" + ) ValidateLoadedPlugin: ValidateLoadedPluginModel = SettingsField( default_factory=ValidateLoadedPluginModel, title="Validate Loaded Plugin" @@ -134,6 +138,11 @@ DEFAULT_PUBLISH_SETTINGS = { "optional": True, "family_plugins_mapping": [] }, + "ValidateNoAnimation": { + "enabled": True, + "optional": True, + "active": False, + }, "ExtractModelObj": { "enabled": True, "optional": True, diff --git a/server_addon/max/server/version.py b/server_addon/max/server/version.py index 1276d0254f..0a8da88258 100644 --- a/server_addon/max/server/version.py +++ b/server_addon/max/server/version.py @@ -1 +1 @@ -__version__ = "0.1.5" +__version__ = "0.1.6" From 999563ea521a877fd9074c52cec00d8ccb21bf77 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 26 Feb 2024 18:31:39 +0800 Subject: [PATCH 21/30] tweak comment and some syntax error --- .../max/plugins/publish/validate_no_animation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py index 9f859a1b28..4f57933085 100644 --- a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py +++ b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py @@ -46,22 +46,22 @@ class ValidateNoAnimation(pyblish.api.InstancePlugin, sel_pos_ctl = rt.getPropertyController( sel.controller, 'Position') ctl_count = (sel_pos_ctl.keys).count - if len(ctl_count) > 0: + if ctl_count > 0: invalid.append( - (sel), f"Object Position(s) has {ctl_count} keyframe(s)") + ( (sel), f"Object Position(s) has {ctl_count} keyframe(s)")) sel_rot_ctl = rt.getPropertyController( sel.controller, "Rotation" ) ctl_count = (sel_rot_ctl.keys).count - if len(ctl_count) > 0: + if ctl_count > 0: invalid.append( - (sel), f"Object Rotation(s) has {ctl_count} keyframe(s)") + ((sel), f"Object Rotation(s) has {ctl_count} keyframe(s)")) sel_scale_ctl = rt.getPropertyController( sel.controller, "Scale" ) ctl_count = (sel_scale_ctl.keys).count - if len(ctl_count) > 0: + if ctl_count > 0: invalid.append( - (sel), f"Object Rotation(s) has {ctl_count} keyframe(s)") + ((sel), f"Object Scale(s) has {ctl_count} keyframe(s)")) return invalid From ef654cd7d8d1cbe3aea4238328aced4082bd9d4a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 26 Feb 2024 20:05:09 +0800 Subject: [PATCH 22/30] use sel.isAnimated instead of doing check on controller --- .../plugins/publish/validate_no_animation.py | 41 ++++++------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py index 4f57933085..0b7a296cd9 100644 --- a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py +++ b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py @@ -27,41 +27,24 @@ class ValidateNoAnimation(pyblish.api.InstancePlugin, return invalid = self.get_invalid(instance) if invalid: - bullet_point_invalid_statement = "\n".join( - "- {}: {}".format(obj, message) - for obj, message in invalid - ) raise PublishValidationError( - "Keyframes found on:\n\n{0}".format( - bullet_point_invalid_statement) + "Keyframes found on:\n\n{0}".format(invalid) , title="Keyframes on model" ) @staticmethod def get_invalid(instance): - invalid = [] - selected_objects = instance.data["members"] - for sel in selected_objects: - sel_pos_ctl = rt.getPropertyController( - sel.controller, 'Position') - ctl_count = (sel_pos_ctl.keys).count - if ctl_count > 0: - invalid.append( - ( (sel), f"Object Position(s) has {ctl_count} keyframe(s)")) - sel_rot_ctl = rt.getPropertyController( - sel.controller, "Rotation" - ) - ctl_count = (sel_rot_ctl.keys).count - if ctl_count > 0: - invalid.append( - ((sel), f"Object Rotation(s) has {ctl_count} keyframe(s)")) - sel_scale_ctl = rt.getPropertyController( - sel.controller, "Scale" - ) - ctl_count = (sel_scale_ctl.keys).count - if ctl_count > 0: - invalid.append( - ((sel), f"Object Scale(s) has {ctl_count} keyframe(s)")) + """Get invalid object(s) which have keyframe(s) + + + Args: + instance (pyblish.api.instance): Instance + + Returns: + list: list of invalid objects + """ + invalid = [invalid for invalid in instance.data["members"] + if invalid.isAnimated] return invalid From fadf820fea6bcd4c40dd7a2ce43f43cf322a3b02 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 28 Feb 2024 18:53:44 +0800 Subject: [PATCH 23/30] improve the code and the error message & docstring --- .../publish/help/validate_model_name.xml | 26 +++ .../plugins/publish/validate_model_name.py | 160 ++++++++++-------- 2 files changed, 116 insertions(+), 70 deletions(-) create mode 100644 client/ayon_core/hosts/max/plugins/publish/help/validate_model_name.xml diff --git a/client/ayon_core/hosts/max/plugins/publish/help/validate_model_name.xml b/client/ayon_core/hosts/max/plugins/publish/help/validate_model_name.xml new file mode 100644 index 0000000000..e41146910a --- /dev/null +++ b/client/ayon_core/hosts/max/plugins/publish/help/validate_model_name.xml @@ -0,0 +1,26 @@ + + + +Invalid Model Name +## Nodes found with Invalid Model Name + +Nodes were detected in your scene which have invalid model name which does not +match the regex you preset in AYON setting. +### How to repair? +Make sure the model name aligns with validation regex in your AYON setting. + + + +### Invalid nodes + +{nodes} + + +### How could this happen? + +This often happens if you have mesh with the model naming does not match +with regex in the setting. + + + + \ No newline at end of file diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py b/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py index 87a9132989..a0cad4e454 100644 --- a/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py +++ b/client/ayon_core/hosts/max/plugins/publish/validate_model_name.py @@ -3,30 +3,34 @@ import re import pyblish.api -from pymxs import runtime as rt from ayon_core.hosts.max.api.action import SelectInvalidAction from ayon_core.pipeline.publish import ( OptionalPyblishPluginMixin, - PublishValidationError, - ValidateContentsOrder) - + PublishXmlValidationError, + ValidateContentsOrder +) class ValidateModelName(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): - """Validate Model Name - Validation regex is (.*)_(?P.*)_(GEO) by default. - e.g. {SOME_RANDOM_NAME}_{YOUR_SUBSET_NAME}_GEO should be your - default model name + """Validate Model Name. - The regex of (?P.*) can be replaced by (?P.*) - and (?P.*). - e.g. - - (.*)_(?P.*)_(GEO) check if your model name is - {SOME_RANDOM_NAME}_{CURRENT_ASSET_NAME}_GEO - - (.*)_(?P.*)_(GEO) check if your model name is - {SOME_RANDOM_NAME}_{CURRENT_PROJECT_NAME}_GEO + Validation regex is `(.*)_(?P.*)_(GEO)` by default. + The setting supports the following regex group name: + - project + - asset + - subset + + Examples: + `{SOME_RANDOM_NAME}_{YOUR_SUBSET_NAME}_GEO` should be your + default model name. + The regex of `(?P.*)` can be replaced by `(?P.*)` + and `(?P.*)`. + `(.*)_(?P.*)_(GEO)` check if your model name is + `{SOME_RANDOM_NAME}_{CURRENT_ASSET_NAME}_GEO` + `(.*)_(?P.*)_(GEO)` check if your model name is + `{SOME_RANDOM_NAME}_{CURRENT_PROJECT_NAME}_GEO` """ optional = True @@ -35,66 +39,82 @@ class ValidateModelName(pyblish.api.InstancePlugin, families = ["model"] label = "Validate Model Name" actions = [SelectInvalidAction] - regex = "" - - @classmethod - def get_invalid(cls, instance): - invalid = [] - model_names = [model.name for model in instance.data.get("members")] - cls.log.debug(model_names) - if not model_names: - cls.log.error("No Model found in the OP Data.") - invalid.append(model_names) - for name in model_names: - invalid_model_name = cls.get_invalid_model_name(instance, name) - invalid.extend(invalid_model_name) - - return invalid - - @classmethod - def get_invalid_model_name(cls, instance, name): - invalid = [] - regex = cls.regex - reg = re.compile(regex) - matched_name = reg.match(name) - project_name = instance.context.data["projectName"] - current_asset_name = instance.context.data["folderPath"] - if matched_name is None: - cls.log.error("invalid model name on: {}".format(name)) - cls.log.error("name doesn't match regex {}".format(regex)) - invalid.append((rt.getNodeByName(name), - "Model name doesn't match regex")) - else: - if "asset" in reg.groupindex: - if matched_name.group("asset") != current_asset_name: - cls.log.error( - "Invalid asset name of the model {}.".format(name) - ) - invalid.append((rt.getNodeByName(name), - "Model with invalid asset name")) - if "subset" in reg.groupindex: - if matched_name.group("subset") != instance.name: - cls.log.error( - "Invalid subset name of the model {}.".format(name) - ) - invalid.append((rt.getNodeByName(name), - "Model with invalid subset name")) - if "project" in reg.groupindex: - if matched_name.group("project") != project_name: - cls.log.error( - "Invalid project name of the model {}.".format(name) - ) - invalid.append((rt.getNodeByName(name), - "Model with invalid project name")) - return invalid + # defined by settings + regex = r"(.*)_(?P.*)_(GEO)" + # cache + regex_compiled = None def process(self, instance): if not self.is_active(instance.data): - self.log.debug("Skipping Validate Model Name...") return invalid = self.get_invalid(instance) + if invalid: + names = "\n".join( + "- {}".format(node.name) for node in invalid + ) + raise PublishXmlValidationError( + plugin=self, + message="Nodes found with invalid model names: {}".format(invalid), + formatting_data={"nodes": names} + ) + + @classmethod + def get_invalid(cls, instance): + if not cls.regex: + cls.log.warning("No regex pattern set. Nothing to validate.") + return + + members = instance.data.get("members") + if not members: + cls.log.error("No members found in the instance.") + return + + cls.regex_compiled = re.compile(cls.regex) + + invalid = [] + for obj in members: + if cls.invalid_name(instance, obj): + invalid.append(obj) + return invalid + + @classmethod + def invalid_name(cls, instance, obj): + """Function to check the object has invalid name + regarding to the validation regex in the AYON setttings + + Args: + instance (pyblish.api.instance): Instance + obj (str): object name + + Returns: + str: invalid object + """ + regex = cls.regex_compiled + name = obj.name + match = regex.match(name) + + if match is None: + cls.log.error("Invalid model name on: %s", name) + cls.log.error("Name doesn't match regex {}".format(regex.pattern)) + return obj + + # Validate regex groups + invalid = False + compare = { + "project": instance.context.data["projectName"], + "asset": instance.context.data["folderPath"], + "subset": instance.context.data["subset"], + } + for key, required_value in compare.items(): + if key in regex.groupindex: + if match.group(key) != required_value: + cls.log.error( + "Invalid %s name for the model %s, " + "required name is %s", + key, name, required_value + ) + invalid = True if invalid: - raise PublishValidationError( - "Model naming is invalid. See the log.") + return obj From a7ad7211b239040f89467c75dee90841f849aab8 Mon Sep 17 00:00:00 2001 From: murphy Date: Tue, 5 Mar 2024 11:56:47 +0100 Subject: [PATCH 24/30] updating tools defaults --- server_addon/applications/server/tools.json | 160 ++++++++++++++++---- server_addon/applications/server/version.py | 2 +- 2 files changed, 128 insertions(+), 34 deletions(-) diff --git a/server_addon/applications/server/tools.json b/server_addon/applications/server/tools.json index 54bee11cf7..3d8f400200 100644 --- a/server_addon/applications/server/tools.json +++ b/server_addon/applications/server/tools.json @@ -1,55 +1,149 @@ { "tool_groups": [ { - "environment": "{\n \"MTOA\": \"{STUDIO_SOFTWARE}/arnold/mtoa_{MAYA_VERSION}_{MTOA_VERSION}\",\n \"MAYA_RENDER_DESC_PATH\": \"{MTOA}\",\n \"MAYA_MODULE_PATH\": \"{MTOA}\",\n \"ARNOLD_PLUGIN_PATH\": \"{MTOA}/shaders\",\n \"MTOA_EXTENSIONS_PATH\": {\n \"darwin\": \"{MTOA}/extensions\",\n \"linux\": \"{MTOA}/extensions\",\n \"windows\": \"{MTOA}/extensions\"\n },\n \"MTOA_EXTENSIONS\": {\n \"darwin\": \"{MTOA}/extensions\",\n \"linux\": \"{MTOA}/extensions\",\n \"windows\": \"{MTOA}/extensions\"\n },\n \"DYLD_LIBRARY_PATH\": {\n \"darwin\": \"{MTOA}/bin\"\n },\n \"PATH\": {\n \"windows\": \"{PATH};{MTOA}/bin\"\n }\n}", - "name": "mtoa", - "label": "Autodesk Arnold", + "name": "htoa", + "label": "Arnold for Houdini (example)", "variants": [ { + "name": "5-4-2-7", + "label": "", + "host_names": [ + "houdini" + ], + "environment": "{\n \"HTOA_VERSION\": \"5.4.2.7\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"HOUDINI_PATH\": [\n \"{STUDIO_SW}/APP/HTOA/{HTOA_VERSION}/HOUDINI{HOUDINI_VERSION}/WINDOWS/htoa-6.1.3.3_rdb15014_houdini-{HTOA_VERSION}\",\n \"{HOUDINI_PATH}\"\n ],\n \"PATH\": {\n \"windows\": [\n \"{STUDIO_SW}/APP/HTOA/{HTOA_VERSION}/HOUDINI{HOUDINI_VERSION}/WINDOWS/htoa-6.1.3.3_rdb15014_houdini-{HTOA_VERSION}/scripts/bin\",\n \"{PATH}\"\n ]\n }\n}" + }, + { + "name": "mtoa", + "label": "Arnold for Maya (example)", + "variants": [ + { + "name": "5-3-1-0", + "label": "", "host_names": [], - "app_variants": [], - "environment": "{\n \"MTOA_VERSION\": \"3.2\"\n}", - "name": "3-2", - "label": "3.2" + "environment": "{\n \"MTOA_VERSION\": \"5.3.1.0\"\n}", + "app_variants": [] }, { + "name": "5-3-4-1", + "label": "", "host_names": [], - "app_variants": [], - "environment": "{\n \"MTOA_VERSION\": \"3.1\"\n}", - "name": "3-1", - "label": "3.1" + "environment": "{\n \"MTOA_VERSION\": \"5.3.4.1\"\n}", + "app_variants": [] } - ] + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"MTOA\": {\n \"darwin\": \"{STUDIO_SW}/APP/MTOA/{MTOA_VERSION}/MAYA{MAYA_VERSION}/MAC\",\n \"linux\": \"{STUDIO_SW}/APP/MTOA/{MTOA_VERSION}/MAYA{MAYA_VERSION}/LINUX\",\n \"windows\": \"{STUDIO_SW}/APP/MTOA/{MTOA_VERSION}/MAYA{MAYA_VERSION}/WINDOWS\"\n },\n \"MAYA_MODULE_PATH\": [\n \"{STUDIO_SW}/APP/MTOA\",\n \"{MAYA_MODULE_PATH}\"\n ],\n \"DYLD_LIBRARY_PATH\": {\n \"darwin\": \"{MTOA}/bin\"\n },\n \"PATH\": {\n \"windows\": [\n \"{MTOA}/bin\",\n \"{PATH}\"\n ]\n },\n \"XBMLANGPATH\": [\n \"{MTOA}/icons\",\n \"{XBMLANGPATH}\"\n ],\n \"MAYA_RENDER_DESC_PATH\": [\n \"{MTOA}\",\n \"{MAYA_RENDER_DESC_PATH}\"\n ],\n \"MTOA_STARTUP_LOG_VERBOSITY\": \"3\"\n}" }, { - "environment": "{}", - "name": "vray", - "label": "Chaos Group Vray", - "variants": [] - }, - { - "environment": "{}", - "name": "yeti", - "label": "Peregrine Labs Yeti", - "variants": [] - }, - { - "environment": "{}", - "name": "renderman", - "label": "Pixar Renderman", + "name": "redshiftMaya", + "label": "Redshift for Maya (example)", "variants": [ { + "name": "3-5-23", + "label": "", + "host_names": [], + "environment": "{\n \"REDSHIFT_VERSION\": \"3.5.23\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"REDSHIFT_COREDATAPATH\": {\n \"darwin\": \"{STUDIO_SW}/APP/REDSHIFT/{REDSHIFT_VERSION}/MAC\",\n \"linux\": \"{STUDIO_SW}/APP/REDSHIFT/{REDSHIFT_VERSION}/LINUX\",\n \"windows\": \"{STUDIO_SW}/APP/REDSHIFT/{REDSHIFT_VERSION}/WINDOWS\"\n },\n \"REDSHIFT_ABORTONLICENSEFAIL\": \"0\",\n \"MAYA_MODULE_PATH\": [\n \"{STUDIO_SW}/APP/REDSHIFT\",\n \"{MAYA_MODULE_PATH}\"\n ],\n \"MAYA_PLUG_IN_PATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Plugins/Maya/{MAYA_VERSION}/nt-x86-64\",\n \"{MAYA_PLUG_IN_PATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/{MAYA_VERSION}\",\n \"{MAYA_PLUG_IN_PATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/{MAYA_VERSION}\",\n \"{MAYA_PLUG_IN_PATH}\"\n ]\n },\n \"MAYA_SCRIPT_PATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Plugins/Maya/Common/scripts\",\n \"{MAYA_SCRIPT_PATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/scripts\",\n \"{MAYA_SCRIPT_PATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/scripts\",\n \"{MAYA_SCRIPT_PATH}\"\n ]\n },\n \"REDSHIFT_PROCEDURALSPATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Procedurals\",\n \"{REDSHIFT_PROCEDURALSPATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/procedurals\",\n \"{REDSHIFT_PROCEDURALSPATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/procedurals\",\n \"{REDSHIFT_PROCEDURALSPATH}\"\n ]\n },\n \"REDSHIFT_MAYAEXTENSIONSPATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Plugins/Maya/{MAYA_VERSION}/nt-x86-64/extensions\",\n \"{REDSHIFT_MAYAEXTENSIONSPATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/{MAYA_VERSION}/extensions\",\n \"{REDSHIFT_MAYAEXTENSIONSPATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/{MAYA_VERSION}/extensions\",\n \"{REDSHIFT_MAYAEXTENSIONSPATH}\"\n ]\n },\n \"XBMLANGPATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Plugins/Maya/Common/icons\",\n \"{XBMLANGPATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/icons\",\n \"{XBMLANGPATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/icons\",\n \"{XBMLANGPATH}\"\n ]\n },\n \"MAYA_RENDER_DESC_PATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Plugins/Maya/Common/rendererDesc\",\n \"{MAYA_RENDER_DESC_PATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/rendererDesc\",\n \"{MAYA_RENDER_DESC_PATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/rendererDesc\",\n \"{MAYA_RENDER_DESC_PATH}\"\n ]\n },\n \"MAYA_CUSTOM_TEMPLATE_PATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Plugins/Maya/Common/scripts/NETemplates\",\n \"{MAYA_CUSTOM_TEMPLATE_PATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/scripts/NETemplates\",\n \"{MAYA_CUSTOM_TEMPLATE_PATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/redshift4maya/common/scripts/NETemplates\",\n \"{MAYA_CUSTOM_TEMPLATE_PATH}\"\n ]\n },\n \"PATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/bin\",\n \"{PATH}\"\n ]\n }\n}" + }, + { + "name": "redshift3dsmax", + "label": "Redshift for 3dsmax (example)", + "variants": [ + { + "name": "3-5-19", + "label": "", + "host_names": [ + "max" + ], + "environment": "{\n \"REDSHIFT_VERSION\": \"3.5.19\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"REDSHIFT_COREDATAPATH\": {\n \"darwin\": \"{STUDIO_SW}/APP/REDSHIFT/{REDSHIFT_VERSION}/MAC\",\n \"linux\": \"{STUDIO_SW}/APP/REDSHIFT/{REDSHIFT_VERSION}/LINUX\",\n \"windows\": \"{STUDIO_SW}/APP/REDSHIFT/{REDSHIFT_VERSION}/WINDOWS\"\n },\n \"REDSHIFT_ABORTONLICENSEFAIL\": \"0\",\n \"REDSHIFT_PROCEDURALSPATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/Procedurals\",\n \"{REDSHIFT_PROCEDURALSPATH}\"\n ],\n \"linux\": [\n \"{REDSHIFT_COREDATAPATH}/procedurals\",\n \"{REDSHIFT_PROCEDURALSPATH}\"\n ],\n \"darwin\": [\n \"{REDSHIFT_COREDATAPATH}/procedurals\",\n \"{REDSHIFT_PROCEDURALSPATH}\"\n ]\n },\n \"PATH\": {\n \"windows\": [\n \"{REDSHIFT_COREDATAPATH}/bin\",\n \"{PATH}\"\n ]\n }\n}" + }, + { + "name": "rendermanMaya", + "label": "Renderman for Maya (example)", + "variants": [ + { + "name": "24-3-maya", + "label": "24.3 RFM", "host_names": [ "maya" ], + "environment": "{\n \"RFMTREE\": {\n \"windows\": \"C:\\\\Program Files\\\\Pixar\\\\RenderManForMaya-24.3\",\n \"darwin\": \"/Applications/Pixar/RenderManForMaya-24.3\",\n \"linux\": \"/opt/pixar/RenderManForMaya-24.3\"\n },\n \"RMANTREE\": {\n \"windows\": \"C:\\\\Program Files\\\\Pixar\\\\RenderManProServer-24.3\",\n \"darwin\": \"/Applications/Pixar/RenderManProServer-24.3\",\n \"linux\": \"/opt/pixar/RenderManProServer-24.3\"\n }\n}", "app_variants": [ "maya/2022" - ], - "environment": "{\n \"RFMTREE\": {\n \"windows\": \"C:\\\\Program Files\\\\Pixar\\\\RenderManForMaya-24.3\",\n \"darwin\": \"/Applications/Pixar/RenderManForMaya-24.3\",\n \"linux\": \"/opt/pixar/RenderManForMaya-24.3\"\n },\n \"RMANTREE\": {\n \"windows\": \"C:\\\\Program Files\\\\Pixar\\\\RenderManProServer-24.3\",\n \"darwin\": \"/Applications/Pixar/RenderManProServer-24.3\",\n \"linux\": \"/opt/pixar/RenderManProServer-24.3\"\n }\n}", - "name": "24-3-maya", - "label": "24.3 RFM" + ] } - ] + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"RFMTREE\": {\n \"darwin\": \"{STUDIO_SW}/APP/RENDERMAN/{RM_VERSION}/MAC/MAYA\",\n \"linux\": \"{STUDIO_SW}/APP/RENDERMAN/{RM_VERSION}/LINUX/MAYA\",\n \"windows\": \"{STUDIO_SW}/APP/RENDERMAN/{RM_VERSION}/WINDOWS/MAYA\"\n },\n \"RMANTREE\": {\n \"darwin\": \"{STUDIO_SW}/APP/RENDERMAN/{RM_VERSION}/MAC/RenderManProServer-{RM_VERSION}\",\n \"linux\": \"{STUDIO_SW}/APP/RENDERMAN/{RM_VERSION}/LINUX/RenderManProServer-{RM_VERSION}\",\n \"windows\": \"{STUDIO_SW}/APP/RENDERMAN/{RM_VERSION}/WINDOWS/RenderManProServer-{RM_VERSION}\"\n },\n \"MAYA_MODULE_PATH\": [\n \"{STUDIO_SW}/APP/RENDERMAN\",\n \"{MAYA_MODULE_PATH}\"\n ],\n \"PIXAR_LICENSE_FILE\": \"{STUDIO_SW}/APP/RENDERMAN/pixar.license\",\n \"RFM_DO_NOT_CREATE_MODULE_FILE\": \"1\"\n}" + }, + { + "name": "mGear", + "label": "mGear for Maya (example)", + "variants": [ + { + "name": "4-0-7", + "label": "", + "host_names": [], + "environment": "{\n \"MGEAR_VERSION\": \"4.0.7\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"MGEAR_ROOT\": \"{STUDIO_SW}/APP/MGEAR/{MGEAR_VERSION}/MAYA{MAYA_VERSION}/windows/x64\",\n \"MAYA_MODULE_PATH\": [\n \"{STUDIO_SW}/APP/MGEAR/{MGEAR_VERSION}/release\",\n \"{MAYA_MODULE_PATH}\"\n ]\n}" + }, + { + "name": "yetiMaya", + "label": "Yeti for Maya (example)", + "variants": [ + { + "name": "4.2.11", + "label": "", + "host_names": [], + "environment": "{\n \"YETI_VERSION\": \"4.2.11\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"YETI_HOME\": {\n \"darwin\": \"{STUDIO_SW}/APP/YETI/{YETI_VERSION}/MAYA{MAYA_VERSION}/MAC\",\n \"linux\": \"{STUDIO_SW}/APP/YETI/{YETI_VERSION}/MAYA{MAYA_VERSION}/LINUX\",\n \"windows\": \"{STUDIO_SW}/APP/YETI/{YETI_VERSION}/MAYA{MAYA_VERSION}/WINDOWS\"\n },\n \"YETI_TMP\": {\n \"windows\": \"C:/temp\",\n \"darwin\": \"/tmp\",\n \"linux\": \"/tmp\"\n },\n \"peregrinel_LICENSE\": \"4202@35.158.197.250\",\n \"MAYA_MODULE_PATH\": [\n \"{STUDIO_SW}/APP/YETI\",\n \"{MAYA_MODULE_PATH}\"\n ]\n}" + }, + { + "name": "vrayMaya", + "label": "Vray for Maya (example)", + "variants": [ + { + "name": "6.10.01", + "label": "", + "host_names": [ + "" + ], + "environment": "{\n \"VRAY_VERSION\": \"6.10.01\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"MAYA_MODULE_PATH\": {\n \"windows\": [\n \"{STUDIO_SW}/APP/VRAY/{VRAY_VERSION}/MAYA{MAYA_VERSION}/WINDOWS/maya_root/modules\",\n \"{MAYA_MODULE_PATH}\"\n ],\n \"linux\": [\n \"{STUDIO_SW}/APP/VRAY/{VRAY_VERSION}/MAYA{MAYA_VERSION}/LINUX/maya_root/modules\",\n \"{MAYA_MODULE_PATH}\"\n ],\n \"darwin\": [\n \"{STUDIO_SW}/APP/VRAY/{VRAY_VERSION}/MAYA{MAYA_VERSION}/MAC/maya_root/modules\",\n \"{MAYA_MODULE_PATH}\"\n ]\n },\n \"VRAY_AUTH_CLIENT_FILE_PATH\": \"{STUDIO_SW}/APP/VRAY\"\n}" + }, + { + "name": "vraynuke", + "label": "Vray for Nuke (example)", + "variants": [ + { + "name": "5-20-00", + "label": "", + "host_names": [ + "nuke" + ], + "environment": "{\n \"VRAYNUKE_VERSION\": \"5.20.00\"\n}", + "app_variants": [] + } + ], + "environment": "{\n \"_comment_\": \"{STUDIO_SW} points to software repository. Can be defined in Core addon globally\",\n\n \"VRAY_FOR_NUKE_13_0_PLUGINS\": {\n \"windows\": \"{STUDIO_SW}/APP/VRAYNUKE/{VRAYNUKE_VERSION}/NUKE{NUKE_VRAY_VERSION}/WINDOWS/nuke_vray/plugins/vray\"\n },\n \"NUKE_PATH\": {\n \"windows\": [\n \"{STUDIO_SW}/APP/VRAYNUKE/{VRAYNUKE_VERSION}/NUKE{NUKE_VRAY_VERSION}/WINDOWS/nuke_root\",\n \"{NUKE_PATH}\"\n ]\n },\n \"PATH\": {\n \"windows\": [\n \"{STUDIO_SW}/APP/VRAYNUKE/{VRAYNUKE_VERSION}/NUKE{NUKE_VRAY_VERSION}/WINDOWS/nuke_vray\",\n \"{PATH}\"\n ]\n },\n \"VRAY_AUTH_CLIENT_FILE_PATH\": \"{STUDIO_SW}/APP/VRAY\"\n}" } ] -} +} \ No newline at end of file diff --git a/server_addon/applications/server/version.py b/server_addon/applications/server/version.py index 0a8da88258..f1380eede2 100644 --- a/server_addon/applications/server/version.py +++ b/server_addon/applications/server/version.py @@ -1 +1 @@ -__version__ = "0.1.6" +__version__ = "0.1.7" From dad4bbe9d41cc9a6af50bad4b5ca3a7ad52c7685 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 5 Mar 2024 13:36:24 +0100 Subject: [PATCH 25/30] Update plugin settings title and version number. - Updated a plugin setting title to "Product types" from "Sync workfile versions for families". - Increased the version number from "0.1.9" to "0.1.10". --- server_addon/nuke/server/settings/publish_plugins.py | 2 +- server_addon/nuke/server/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server_addon/nuke/server/settings/publish_plugins.py b/server_addon/nuke/server/settings/publish_plugins.py index 02ee9b3bab..7d9c914fee 100644 --- a/server_addon/nuke/server/settings/publish_plugins.py +++ b/server_addon/nuke/server/settings/publish_plugins.py @@ -56,7 +56,7 @@ class CollectInstanceDataModel(BaseSettingsModel): sync_workfile_version_on_product_types: list[str] = SettingsField( default_factory=list, enum_resolver=nuke_product_types_enum, - title="Sync workfile versions for familes" + title="Product types" ) diff --git a/server_addon/nuke/server/version.py b/server_addon/nuke/server/version.py index c11f861afb..569b1212f7 100644 --- a/server_addon/nuke/server/version.py +++ b/server_addon/nuke/server/version.py @@ -1 +1 @@ -__version__ = "0.1.9" +__version__ = "0.1.10" From 2caf32c5b05f0153a8f1c25ad80cb08301d6d6e3 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 6 Mar 2024 23:08:40 +0800 Subject: [PATCH 26/30] supports the check on only one keyframe in timeline --- .../plugins/publish/validate_no_animation.py | 19 ++++++++++++++++++- server_addon/max/server/version.py | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py index 0b7a296cd9..4b2a18d606 100644 --- a/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py +++ b/client/ayon_core/hosts/max/plugins/publish/validate_no_animation.py @@ -8,6 +8,23 @@ from ayon_core.pipeline import ( from ayon_core.hosts.max.api.action import SelectInvalidAction +def get_invalid_keys(obj): + """function to check on whether there is keyframe in + + Args: + obj (str): object needed to check if there is a keyframe + + Returns: + bool: whether invalid object(s) exist + """ + for transform in ["Position", "Rotation", "Scale"]: + num_of_key = rt.NumKeys(rt.getPropertyController( + obj.controller, transform)) + if num_of_key > 0: + return True + return False + + class ValidateNoAnimation(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): """Validates No Animation @@ -45,6 +62,6 @@ class ValidateNoAnimation(pyblish.api.InstancePlugin, list: list of invalid objects """ invalid = [invalid for invalid in instance.data["members"] - if invalid.isAnimated] + if invalid.isAnimated or get_invalid_keys(invalid)] return invalid diff --git a/server_addon/max/server/version.py b/server_addon/max/server/version.py index 0a8da88258..f1380eede2 100644 --- a/server_addon/max/server/version.py +++ b/server_addon/max/server/version.py @@ -1 +1 @@ -__version__ = "0.1.6" +__version__ = "0.1.7" From fd8bf2cc67d03d9e7b80c903e1d6ccb40d6c0df0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Mar 2024 16:29:12 +0100 Subject: [PATCH 27/30] Adjust clip start if slate is present Trim the clip's start time by 1 frame and update its duration accordingly when a "slate" is detected in the version data families. Also, corrected calculation for `frame_end_handle` to use `frame_end`. --- client/ayon_core/hosts/resolve/api/plugin.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/hosts/resolve/api/plugin.py b/client/ayon_core/hosts/resolve/api/plugin.py index 157b8de363..dfce3ea37a 100644 --- a/client/ayon_core/hosts/resolve/api/plugin.py +++ b/client/ayon_core/hosts/resolve/api/plugin.py @@ -410,6 +410,11 @@ class ClipLoader: source_out = int(_clip_property("End")) source_duration = int(_clip_property("Frames")) + # Trim clip start if slate is present + if "slate" in self.data["versionData"]["families"]: + source_in += 1 + source_duration = source_out - source_in + 1 + if not self.with_handles: # Load file without the handles of the source media # We remove the handles from the source in and source out @@ -435,7 +440,7 @@ class ClipLoader: handle_start = version_data.get("handleStart", 0) handle_end = version_data.get("handleEnd", 0) frame_start_handle = frame_start - handle_start - frame_end_handle = frame_start + handle_end + frame_end_handle = frame_end + handle_end database_frame_duration = int( frame_end_handle - frame_start_handle + 1 ) From b5873d47a8c8b9f4d812421bee0221f4ad7b7030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Wed, 6 Mar 2024 16:44:18 +0100 Subject: [PATCH 28/30] Update bug_report.yml --- .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 5a0ed1ae1d..e6badf936a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,6 @@ name: Bug Report description: File a bug report -title: '' +title: 'Your issue title here' labels: - 'type: bug' body: From 14db89cc359c2240727a24cc832e1733dbb67414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Wed, 6 Mar 2024 16:45:43 +0100 Subject: [PATCH 29/30] Update enhancement_request.yml --- .github/ISSUE_TEMPLATE/enhancement_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.yml b/.github/ISSUE_TEMPLATE/enhancement_request.yml index da4d0d9319..31b2eb2edd 100644 --- a/.github/ISSUE_TEMPLATE/enhancement_request.yml +++ b/.github/ISSUE_TEMPLATE/enhancement_request.yml @@ -1,6 +1,6 @@ name: Enhancement Request description: Create a report to help us enhance a particular feature -title: "" +title: "Your issue title here" labels: - "type: enhancement" body: @@ -49,4 +49,4 @@ body: label: "Additional context:" description: Add any other context or screenshots about the enhancement request here. validations: - required: false \ No newline at end of file + required: false From 7b19e06787dc00681369126136e0cc76d7fa4d82 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 8 Mar 2024 19:37:03 +0800 Subject: [PATCH 30/30] removing remove instances --- .../hosts/max/plugins/create/create_workfile.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/client/ayon_core/hosts/max/plugins/create/create_workfile.py b/client/ayon_core/hosts/max/plugins/create/create_workfile.py index 1552149413..058fe10eb2 100644 --- a/client/ayon_core/hosts/max/plugins/create/create_workfile.py +++ b/client/ayon_core/hosts/max/plugins/create/create_workfile.py @@ -98,21 +98,6 @@ class CreateWorkfile(plugin.MaxCreatorBase, AutoCreator): created_inst.data_to_store() ) - def remove_instances(self, instances): - """Remove specified instance from the scene. - - This is only removing `id` parameter so instance is no longer - instance, because it might contain valuable data for artist. - - """ - for instance in instances: - instance_node = rt.GetNodeByName( - instance.data.get("instance_node")) - if instance_node: - rt.Delete(instance_node) - - self._remove_instance_from_context(instance) - def create_node(self, product_name): if rt.getNodeByName(product_name): node = rt.getNodeByName(product_name)