supports families check before the validation of loaded plugins

This commit is contained in:
Kayla Man 2023-11-02 12:27:22 +08:00
parent 1ecd96acf6
commit 881340b60a
6 changed files with 74 additions and 25 deletions

View file

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Validator for Loaded Plugin.""" """Validator for Loaded Plugin."""
from pyblish.api import ContextPlugin, ValidatorOrder import os
from pyblish.api import InstancePlugin, ValidatorOrder
from pymxs import runtime as rt from pymxs import runtime as rt
from openpype.pipeline.publish import ( from openpype.pipeline.publish import (
RepairContextAction, RepairAction,
OptionalPyblishPluginMixin, OptionalPyblishPluginMixin,
PublishValidationError PublishValidationError
) )
@ -12,7 +13,7 @@ from openpype.hosts.max.api.lib import get_plugins
class ValidateLoadedPlugin(OptionalPyblishPluginMixin, class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
ContextPlugin): InstancePlugin):
"""Validates if the specific plugin is loaded in 3ds max. """Validates if the specific plugin is loaded in 3ds max.
Studio Admin(s) can add the plugins they want to check in validation Studio Admin(s) can add the plugins they want to check in validation
via studio defined project settings""" via studio defined project settings"""
@ -21,17 +22,17 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
hosts = ["max"] hosts = ["max"]
label = "Validate Loaded Plugins" label = "Validate Loaded Plugins"
optional = True optional = True
actions = [RepairContextAction] actions = [RepairAction]
def get_invalid(self, context): def get_invalid(self, instance):
"""Plugin entry point.""" """Plugin entry point."""
if not self.is_active(context.data): if not self.is_active(instance.data):
self.log.debug("Skipping Validate Loaded Plugin...") self.log.debug("Skipping Validate Loaded Plugin...")
return return
required_plugins = ( required_plugins = (
context.data["project_settings"]["max"]["publish"] instance.context.data["project_settings"]["max"]["publish"]
["ValidateLoadedPlugin"]["plugins_for_check"] ["ValidateLoadedPlugin"]["family_plugins_mapping"]
) )
if not required_plugins: if not required_plugins:
@ -45,9 +46,21 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
get_plugins()) get_plugins())
} }
for plugin in required_plugins: for families, plugin in required_plugins.items():
plugin_name = plugin.lower() families_list = families.split(",")
excluded_families = [family for family in families_list
if instance.data["family"]!=family
and family!="_"]
if excluded_families:
self.log.debug("The {} instance is not part of {}.".format(
instance.data["family"], excluded_families
))
return
if not plugin:
return
plugin_name = plugin.format(**os.environ).lower()
plugin_index = available_plugins.get(plugin_name) plugin_index = available_plugins.get(plugin_name)
if plugin_index is None: if plugin_index is None:
@ -61,8 +74,8 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
return invalid return invalid
def process(self, context): def process(self, instance):
invalid_plugins = self.get_invalid(context) invalid_plugins = self.get_invalid(instance)
if invalid_plugins: if invalid_plugins:
bullet_point_invalid_statement = "\n".join( bullet_point_invalid_statement = "\n".join(
"- {}".format(invalid) for invalid in invalid_plugins "- {}".format(invalid) for invalid in invalid_plugins
@ -76,18 +89,30 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin,
report, title="Required Plugins unloaded") report, title="Required Plugins unloaded")
@classmethod @classmethod
def repair(cls, context): def repair(cls, instance):
# get all DLL loaded plugins in Max and their plugin index # get all DLL loaded plugins in Max and their plugin index
available_plugins = { available_plugins = {
plugin_name.lower(): index for index, plugin_name in enumerate( plugin_name.lower(): index for index, plugin_name in enumerate(
get_plugins()) get_plugins())
} }
required_plugins = ( required_plugins = (
context.data["project_settings"]["max"]["publish"] instance.context.data["project_settings"]["max"]["publish"]
["ValidateLoadedPlugin"]["plugins_for_check"] ["ValidateLoadedPlugin"]["family_plugins_mapping"]
) )
for plugin in required_plugins: for families, plugin in required_plugins.items():
plugin_name = plugin.lower() families_list = families.split(",")
excluded_families = [family for family in families_list
if instance.data["family"]!=family
and family!="_"]
if excluded_families:
cls.log.debug("The {} instance is not part of {}.".format(
instance.data["family"], excluded_families
))
continue
if not plugin:
continue
plugin_name = plugin.format(**os.environ).lower()
plugin_index = available_plugins.get(plugin_name) plugin_index = available_plugins.get(plugin_name)
if plugin_index is None: if plugin_index is None:

View file

@ -24,6 +24,7 @@ class CollectSceneVersion(pyblish.api.ContextPlugin):
"hiero", "hiero",
"houdini", "houdini",
"maya", "maya",
"max",
"nuke", "nuke",
"photoshop", "photoshop",
"resolve", "resolve",

View file

@ -640,6 +640,19 @@ def _convert_3dsmax_project_settings(ayon_settings, output):
} }
ayon_max["PointCloud"]["attribute"] = new_point_cloud_attribute ayon_max["PointCloud"]["attribute"] = new_point_cloud_attribute
ayon_publish = ayon_max["publish"]
if "ValidateLoadedPlugin" in ayon_publish:
family_plugin_mapping = (
ayon_publish["ValidateLoadedPlugin"]["family_plugins_mapping"]
)
new_family_plugin_mapping = {
item["families"]: item["plugins"]
for item in family_plugin_mapping
}
ayon_max["ValidateLoadedPlugin"]["family_plugins_mapping"] = (
new_family_plugin_mapping
)
output["max"] = ayon_max output["max"] = ayon_max

View file

@ -40,7 +40,7 @@
"ValidateLoadedPlugin": { "ValidateLoadedPlugin": {
"enabled": false, "enabled": false,
"optional": true, "optional": true,
"plugins_for_check": [] "family_plugins_mapping": {}
} }
} }
} }

View file

@ -47,10 +47,14 @@
"label": "Optional" "label": "Optional"
}, },
{ {
"type": "list", "type": "dict-modifiable",
"key": "plugins_for_check", "collapsible": true,
"label": "Plugins Needed For Check", "key": "family_plugins_mapping",
"object_type": "text" "label": "Family Plugins Mapping",
"use_label_wrap": true,
"object_type": {
"type": "text"
}
} }
] ]
} }

View file

@ -3,11 +3,17 @@ from pydantic import Field
from ayon_server.settings import BaseSettingsModel from ayon_server.settings import BaseSettingsModel
class FamilyPluginsMappingModel(BaseSettingsModel):
_layout = "compact"
families: str = Field(title="Families")
plugins: str = Field(title="Plugins")
class ValidateLoadedPluginModel(BaseSettingsModel): class ValidateLoadedPluginModel(BaseSettingsModel):
enabled: bool = Field(title="ValidateLoadedPlugin") enabled: bool = Field(title="ValidateLoadedPlugin")
optional: bool = Field(title="Optional") optional: bool = Field(title="Optional")
plugins_for_check: list[str] = Field( family_plugins_mapping: list[FamilyPluginsMappingModel] = Field(
default_factory=list, title="Plugins Needed For Check" default_factory=list, title="Family Plugins Mapping"
) )
@ -37,6 +43,6 @@ DEFAULT_PUBLISH_SETTINGS = {
"ValidateLoadedPlugin": { "ValidateLoadedPlugin": {
"enabled": False, "enabled": False,
"optional": True, "optional": True,
"plugins_for_check": [] "family_plugins_mapping": {}
} }
} }