From 0403af298e795cdc7a206b88485f40bd6e07072b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 9 Nov 2023 17:21:37 +0800 Subject: [PATCH] tweaks the codes to use list instead of dict for OP settings --- .../plugins/publish/validate_loaded_plugin.py | 141 +++++++++--------- .../defaults/project_settings/max.json | 2 +- .../schemas/schema_max_publish.json | 10 +- 3 files changed, 77 insertions(+), 76 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_loaded_plugin.py b/openpype/hosts/max/plugins/publish/validate_loaded_plugin.py index 06486e94a6..7450c8f971 100644 --- a/openpype/hosts/max/plugins/publish/validate_loaded_plugin.py +++ b/openpype/hosts/max/plugins/publish/validate_loaded_plugin.py @@ -17,9 +17,6 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin, """Validates if the specific plugin is loaded in 3ds max. Studio Admin(s) can add the plugins they want to check in validation via studio defined project settings - If families = ["*"], all the required plugins would be validated - If families - """ order = pyblish.api.ValidatorOrder @@ -30,66 +27,77 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin, family_plugins_mapping = {} - def get_invalid(self, instance): + @classmethod + def get_invalid(cls, instance): """Plugin entry point.""" - if not self.is_active(instance.data): - self.log.debug("Skipping Validate Loaded Plugin...") - return - - required_plugins = self.family_plugins_mapping - if not required_plugins: + family_plugins_mapping = cls.family_plugins_mapping + if not family_plugins_mapping: return invalid = [] + # Find all plug-in requirements for current instance + instance_families = {instance.data["family"]} + instance_families.update(instance.data.get("families", [])) + cls.log.debug("Checking plug-in validation " + f"for instance families: {instance_families}") + all_required_plugins = set() + + for mapping in family_plugins_mapping: + # Check for matching families + if not mapping: + return + + match_families = {fam for fam in mapping["families"] if fam.strip()} + has_match = "*" in match_families or match_families.intersection( + instance_families) + + if not has_match: + continue + + cls.log.debug(f"Found plug-in family requirements: {match_families}") + required_plugins = [ + # match lowercase and format with os.environ to allow + # plugin names defined by max version, e.g. {3DSMAX_VERSION} + plugin.format(**os.environ).lower() + for plugin in mapping["plugins"] + # ignore empty fields in settings + if plugin.strip() + ] + + all_required_plugins.update(required_plugins) + + if not all_required_plugins: + # Instance has no plug-in requirements + return # get all DLL loaded plugins in Max and their plugin index available_plugins = { plugin_name.lower(): index for index, plugin_name in enumerate( get_plugins()) } - - # Build instance families lookup - instance_families = {instance.data["family"]} - instance_families.update(instance.data.get("families", [])) - self.log.debug("Checking plug-in validation " - f"for instance families: {instance_families}") - for family in required_plugins: - # Check for matching families - match_families = {fam.strip() for fam in - family.split(",") if fam.strip()} - self.log.debug(f"Plug-in family requirements: {match_families}") - has_match = "*" in match_families or match_families.intersection( - instance_families) - - if not has_match: + # validate the required plug-ins + for plugin in sorted(all_required_plugins): + plugin_index = available_plugins.get(plugin) + if plugin_index is None: + debug_msg = ( + f"Plugin {plugin} does not exist" + " in 3dsMax Plugin List." + ) + invalid.append((plugin, debug_msg)) continue - plugins = [plugin for plugin in - required_plugins[family]["plugins"]] - for plugin in plugins: - if not plugin: - return - # make sure the validation applied for - # plugins with different Max version - plugin_name = plugin.format(**os.environ).lower() - plugin_index = available_plugins.get(plugin_name) - - if plugin_index is None: - invalid.append( - f"Plugin {plugin} does not exist" - " in 3dsMax Plugin List." - ) - continue - - if not rt.pluginManager.isPluginDllLoaded(plugin_index): - invalid.append(f"Plugin {plugin} not loaded.") - + if not rt.pluginManager.isPluginDllLoaded(plugin_index): + debug_msg = f"Plugin {plugin} not loaded." + invalid.append((plugin, debug_msg)) return invalid def process(self, instance): - invalid_plugins = self.get_invalid(instance) - if invalid_plugins: + if not self.is_active(instance.data): + self.log.debug("Skipping Validate Loaded Plugin...") + return + invalid = self.get_invalid(instance) + if invalid: bullet_point_invalid_statement = "\n".join( - "- {}".format(invalid) for invalid in invalid_plugins + "- {}".format(message) for _, message in invalid ) report = ( "Required plugins are not loaded.\n\n" @@ -101,36 +109,23 @@ class ValidateLoadedPlugin(OptionalPyblishPluginMixin, @classmethod def repair(cls, instance): + # get all DLL loaded plugins in Max and their plugin index + invalid = cls.get_invalid(instance) + if not invalid: + return + # get all DLL loaded plugins in Max and their plugin index available_plugins = { plugin_name.lower(): index for index, plugin_name in enumerate( get_plugins()) } - required_plugins = cls.family_plugins_mapping - instance_families = {instance.data["family"]} - instance_families.update(instance.data.get("families", [])) - cls.log.debug("Checking plug-in validation " - f"for instance families: {instance_families}") - for family in required_plugins: - match_families = {fam.strip() for fam in - family.split(",") if fam.strip()} - cls.log.debug(f"Plug-in family requirements: {match_families}") - has_match = "*" in match_families or match_families.intersection( - instance_families) - if not has_match: + for invalid_plugin, _ in invalid: + plugin_index = available_plugins.get(invalid_plugin) + + if plugin_index is None: + cls.log.warning(f"Can't enable missing plugin: {invalid_plugin}") continue - plugins = [plugin for plugin in family["plugins"]] - for plugin in plugins: - if not plugin: - return - plugin_name = plugin.format(**os.environ).lower() - plugin_index = available_plugins.get(plugin_name) - - if plugin_index is None: - cls.log.warning(f"Can't enable missing plugin: {plugin}") - continue - - if not rt.pluginManager.isPluginDllLoaded(plugin_index): - rt.pluginManager.loadPluginDll(plugin_index) + if not rt.pluginManager.isPluginDllLoaded(plugin_index): + rt.pluginManager.loadPluginDll(plugin_index) diff --git a/openpype/settings/defaults/project_settings/max.json b/openpype/settings/defaults/project_settings/max.json index 57927b48c7..92049cdbe9 100644 --- a/openpype/settings/defaults/project_settings/max.json +++ b/openpype/settings/defaults/project_settings/max.json @@ -44,7 +44,7 @@ "ValidateLoadedPlugin": { "enabled": false, "optional": true, - "family_plugins_mapping": {} + "family_plugins_mapping": [] } } } 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 c44c7525da..c6d37ae993 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 @@ -66,7 +66,7 @@ "label": "Optional" }, { - "type": "dict-modifiable", + "type": "list", "collapsible": true, "key": "family_plugins_mapping", "label": "Family Plugins Mapping", @@ -74,9 +74,15 @@ "object_type": { "type": "dict", "children": [ + { + "key": "families", + "label": "Famiies", + "type": "list", + "object_type": "text" + }, { "key": "plugins", - "label": "plugins", + "label": "Plugins", "type": "list", "object_type": "text" }