diff --git a/server_addon/maya/client/ayon_maya/plugins/inventory/connect_ornatrix_rig.py b/server_addon/maya/client/ayon_maya/plugins/inventory/connect_ornatrix_rig.py new file mode 100644 index 0000000000..52fc003b65 --- /dev/null +++ b/server_addon/maya/client/ayon_maya/plugins/inventory/connect_ornatrix_rig.py @@ -0,0 +1,124 @@ +import os +import json +from collections import defaultdict + +from maya import cmds, mel + +from ayon_core.pipeline import ( + InventoryAction, + get_repres_contexts, + get_representation_path, +) + + +class ConnectOrnatrixRig(InventoryAction): + """Connect Ornatrix Rig with an animation or pointcache.""" + + label = "Connect Ornatrix Rig" + icon = "link" + color = "white" + + def process(self, containers): + # Categorize containers by product type. + containers_by_product_type = defaultdict(list) + repre_ids = { + container["representation"] + for container in containers + } + repre_contexts_by_id = get_repres_contexts(repre_ids) + for container in containers: + repre_id = container["representation"] + repre_context = repre_contexts_by_id[repre_id] + + product_type = repre_context["product"]["productType"] + + containers_by_product_type.setdefault(product_type, []) + containers_by_product_type[product_type].append(container) + + # Validate to only 1 source container. + source_containers = containers_by_product_type.get("animation", []) + source_containers += containers_by_product_type.get("pointcache", []) + source_container_namespaces = [ + x["namespace"] for x in source_containers + ] + message = ( + "{} animation containers selected:\n\n{}\n\nOnly select 1 of type " + "\"animation\" or \"pointcache\".".format( + len(source_containers), source_container_namespaces + ) + ) + if len(source_containers) != 1: + self.display_warning(message) + return + + source_container = source_containers[0] + source_repre_id = source_container["representation"] + source_namespace = source_container["namespace"] + + # Validate source representation is an alembic. + source_path = get_representation_path( + repre_contexts_by_id[source_repre_id]["representation"] + ).replace("\\", "/") + message = "Animation container \"{}\" is not an alembic:\n{}".format( + source_container["namespace"], source_path + ) + if not source_path.endswith(".abc"): + self.display_warning(message) + return + + ox_rig_containers = containers_by_product_type.get("oxrig") + if not ox_rig_containers: + self.display_warning( + "Select at least one oxrig container" + ) + return + source_nodes = [] + for container in ox_rig_containers: + repre_id = container["representation"] + maya_file = get_representation_path( + repre_contexts_by_id[repre_id]["representation"] + ) + _, ext = os.path.splitext(maya_file) + settings_file = maya_file.replace( + ext, ".rigsettings") + if not os.path.exists(settings_file): + continue + with open(settings_file, "w") as fp: + source_nodes.extend( + item.get("node") for item in json.load(fp)) + grooms_file = maya_file.replace(ext, ".oxg.yaml") + # Compare loaded connections to scene. + for node in source_nodes: + target_node = cmds.ls(f"{source_namespace}:{node}")[0] + if not target_node: + self.display_warning( + "No target node found " + "in \"animation\" or \"pointcache\"." + ) + return + mel.eval(f"OxLoadGroom -path \"{grooms_file}\";") + + def display_warning(self, message, show_cancel=False): + """Show feedback to user. + + Returns: + bool + """ + + from qtpy import QtWidgets + + accept = QtWidgets.QMessageBox.Ok + if show_cancel: + buttons = accept | QtWidgets.QMessageBox.Cancel + else: + buttons = accept + + state = QtWidgets.QMessageBox.warning( + None, + "", + message, + buttons=buttons, + defaultButton=accept + ) + + return state == accept diff --git a/server_addon/maya/client/ayon_maya/plugins/load/load_ornatrix_grooms.py b/server_addon/maya/client/ayon_maya/plugins/load/load_ornatrix_grooms.py index 979e74f626..d4745717c0 100644 --- a/server_addon/maya/client/ayon_maya/plugins/load/load_ornatrix_grooms.py +++ b/server_addon/maya/client/ayon_maya/plugins/load/load_ornatrix_grooms.py @@ -33,7 +33,7 @@ class OxOrnatrixGrooms(plugin.Loader): path = self.filepath_from_context(context) # TODO: load Ox Grooms - nodes = [mel.eval(f'OxLoadGroom -path "{path}";')] + nodes = [mel.eval(f"OxLoadGroom -path \"{path}\";")] group_name = "{}:{}".format(namespace, name) group_node = cmds.group(nodes, name=group_name) diff --git a/server_addon/maya/client/ayon_maya/plugins/publish/collect_ornatrix_rig.py b/server_addon/maya/client/ayon_maya/plugins/publish/collect_ornatrix_rig.py index c0ba0ebd32..a66fe75332 100644 --- a/server_addon/maya/client/ayon_maya/plugins/publish/collect_ornatrix_rig.py +++ b/server_addon/maya/client/ayon_maya/plugins/publish/collect_ornatrix_rig.py @@ -74,6 +74,7 @@ class CollectOxRig(plugin.MayaInstancePlugin): "(searched: %s)" % (texture)) item = { + "node": node, "files": files, "source": texture, "texture_attribute": texture_attr diff --git a/server_addon/maya/client/ayon_maya/plugins/publish/extract_ornatrix_rig.py b/server_addon/maya/client/ayon_maya/plugins/publish/extract_ornatrix_rig.py index 92b858b682..96279328ee 100644 --- a/server_addon/maya/client/ayon_maya/plugins/publish/extract_ornatrix_rig.py +++ b/server_addon/maya/client/ayon_maya/plugins/publish/extract_ornatrix_rig.py @@ -39,7 +39,7 @@ class ExtractOxRig(plugin.MayaExtractorPlugin): # Define extract output file path dirname = self.staging_dir(instance) - settings_path = os.path.join(dirname, "ornatrix.rigsettings") + settings_path = os.path.join(dirname, "ornatrix_rig.rigsettings") image_search_path = instance.data["resourcesDir"] # add textures to transfers @@ -89,6 +89,7 @@ class ExtractOxRig(plugin.MayaExtractorPlugin): preserveReferences=False, constructionHistory=True, shader=False) + # save the groom presets mel.eval(f'OxSaveGroom -path "{ox_groom_path}"') # Ensure files can be stored @@ -106,7 +107,7 @@ class ExtractOxRig(plugin.MayaExtractorPlugin): } ) - self.log.debug("OxGroom file: {}".format(ox_groom_path)) + self.log.debug("OxGrooms file: {}".format(ox_groom_path)) instance.data["representations"].append( { 'name': "yaml",