Skip to content

extract_xgen

ExtractXgen

Bases: MayaExtractorPlugin

Extract Xgen

Workflow: - Duplicate nodes used for patches. - Export palette and import onto duplicate nodes. - Export/Publish duplicate nodes and palette. - Export duplicate palette to .xgen file and add to publish. - Publish all xgen files as resources.

Source code in client/ayon_maya/plugins/publish/extract_xgen.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
class ExtractXgen(plugin.MayaExtractorPlugin):
    """Extract Xgen

    Workflow:
    - Duplicate nodes used for patches.
    - Export palette and import onto duplicate nodes.
    - Export/Publish duplicate nodes and palette.
    - Export duplicate palette to .xgen file and add to publish.
    - Publish all xgen files as resources.
    """

    label = "Extract Xgen"
    families = ["xgen"]
    scene_type = "ma"

    def process(self, instance):
        if "representations" not in instance.data:
            instance.data["representations"] = []

        staging_dir = self.staging_dir(instance)
        maya_filename = "{}.{}".format(instance.data["name"], self.scene_type)
        maya_filepath = os.path.join(staging_dir, maya_filename)

        # Get published xgen file name.
        template_data = copy.deepcopy(instance.data["anatomyData"])
        template_data.update({"ext": "xgen"})
        anatomy = instance.context.data["anatomy"]
        file_template = anatomy.get_template_item("publish", "default", "file")
        xgen_filename = file_template.format(template_data)

        xgen_path = os.path.join(
            self.staging_dir(instance), xgen_filename
        ).replace("\\", "/")
        type = "mayaAscii" if self.scene_type == "ma" else "mayaBinary"

        # Duplicate xgen setup.
        with delete_after() as delete_bin:
            duplicate_nodes = []
            # Collect nodes to export.
            for node in instance.data["xgenConnections"]:
                # Duplicate_transform subd patch geometry.
                duplicate_transform = cmds.duplicate(node)[0]
                delete_bin.append(duplicate_transform)

                # Discard the children.
                shapes = cmds.listRelatives(duplicate_transform, shapes=True)
                children = cmds.listRelatives(
                    duplicate_transform, children=True
                )
                cmds.delete(set(children) - set(shapes))

                if cmds.listRelatives(duplicate_transform, parent=True):
                    duplicate_transform = cmds.parent(
                        duplicate_transform, world=True
                    )[0]

                duplicate_nodes.append(duplicate_transform)

            # Export temp xgen palette files.
            temp_xgen_path = os.path.join(
                tempfile.gettempdir(), "temp.xgen"
            ).replace("\\", "/")
            xgenm.exportPalette(
                instance.data["xgmPalette"].replace("|", ""), temp_xgen_path
            )
            self.log.debug("Extracted to {}".format(temp_xgen_path))

            # Import xgen onto the duplicate.
            with maintained_selection():
                cmds.select(duplicate_nodes)
                palette = xgenm.importPalette(temp_xgen_path, [])

            delete_bin.append(palette)

            # Copy shading assignments.
            nodes = (
                instance.data["xgmDescriptions"] +
                instance.data["xgmSubdPatches"]
            )
            for node in nodes:
                target_node = node.split(":")[-1]
                shading_engine = cmds.listConnections(
                    node, type="shadingEngine"
                )[0]
                cmds.sets(target_node, edit=True, forceElement=shading_engine)

            # Export duplicated palettes.
            xgenm.exportPalette(palette, xgen_path)

            # Export Maya file.
            attribute_data = {"{}.xgFileName".format(palette): xgen_filename}
            with attribute_values(attribute_data):
                with maintained_selection():
                    cmds.select(duplicate_nodes + [palette])
                    cmds.file(
                        maya_filepath,
                        force=True,
                        type=type,
                        exportSelected=True,
                        preserveReferences=False,
                        constructionHistory=True,
                        shader=True,
                        constraints=True,
                        expressions=True
                    )

            self.log.debug("Extracted to {}".format(maya_filepath))

        if os.path.exists(temp_xgen_path):
            os.remove(temp_xgen_path)

        data = {
            "xgDataPath": os.path.join(
                instance.data["resourcesDir"],
                "collections",
                palette.replace(":", "__ns__")
            ).replace("\\", "/"),
            "xgProjectPath": os.path.dirname(
                instance.data["resourcesDir"]
            ).replace("\\", "/")
        }
        write_xgen_file(data, xgen_path)

        # Adding representations.
        representation = {
            "name": "xgen",
            "ext": "xgen",
            "files": xgen_filename,
            "stagingDir": staging_dir,
        }
        instance.data["representations"].append(representation)

        representation = {
            "name": self.scene_type,
            "ext": self.scene_type,
            "files": maya_filename,
            "stagingDir": staging_dir
        }
        instance.data["representations"].append(representation)