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