Ejemplo n.º 1
0
    def extract_mayabinary(self, nodes, outpath):
        import maya.cmds as cmds
        from reveries.maya import capsule

        geo_id_and_hash = None

        with contextlib.nested(
            capsule.no_undo(),
            capsule.no_display_layers(nodes),
            capsule.no_smooth_preview(),
            capsule.maintained_selection(),
            capsule.without_extension(),
        ):

            mesh_nodes = cmds.ls(nodes,
                                 type="mesh",
                                 noIntermediate=True,
                                 long=True)
            clay_shader = "initialShadingGroup"

            # Perform extraction
            cmds.select(nodes, noExpand=True)

            with capsule.undo_chunk_when_no_undo():

                # Remove mesh history, for removing all intermediate nodes
                transforms = cmds.ls(nodes, type="transform")
                cmds.delete(transforms, constructionHistory=True)
                # Remove all stray shapes, ensure no intermediate nodes
                all_meshes = set(cmds.ls(nodes, type="mesh", long=True))
                cmds.delete(list(all_meshes - set(mesh_nodes)))

                geo_id_and_hash = self.hash(set(mesh_nodes))

                with capsule.assign_shader(mesh_nodes,
                                           shadingEngine=clay_shader):
                    cmds.file(
                        outpath,
                        force=True,
                        typ="mayaBinary",
                        exportSelectedStrict=True,
                        preserveReferences=False,
                        # Shader assignment is the responsibility of
                        # riggers, for animators, and lookdev, for
                        # rendering.
                        shader=False,
                        # Construction history inherited from collection
                        # This enables a selective export of nodes
                        # relevant to this particular plug-in.
                        constructionHistory=False,
                        channels=False,
                        constraints=False,
                        expressions=False,
                    )

        return geo_id_and_hash
Ejemplo n.º 2
0
    def extract_mayaBinary(self, packager):
        entry_file = packager.file_name("mb")
        package_path = packager.create_package()
        entry_path = os.path.join(package_path, entry_file)

        mesh_nodes = cmds.ls(self.member,
                             type="mesh",
                             noIntermediate=True,
                             long=True)
        clay_shader = "initialShadingGroup"

        # Perform extraction
        cmds.select(self.member, noExpand=True)

        with contextlib.nested(
            capsule.assign_shader(mesh_nodes, shadingEngine=clay_shader),
            capsule.undo_chunk_when_no_undo(),
        ):
            # Remove mesh history, for removing all intermediate nodes
            transforms = cmds.ls(self.member, type="transform")
            cmds.delete(transforms, constructionHistory=True)
            # Remove all stray shapes, ensure no intermediate nodes
            all_meshes = set(cmds.ls(self.member, type="mesh", long=True))
            cmds.delete(list(all_meshes - set(mesh_nodes)))

            geo_id_and_hash = self.hash(set(mesh_nodes))
            packager.add_data({"modelProfile": geo_id_and_hash})

            cmds.file(
                entry_path,
                force=True,
                typ="mayaBinary",
                exportSelected=True,
                preserveReferences=False,
                # Shader assignment is the responsibility of
                # riggers, for animators, and lookdev, for
                # rendering.
                shader=False,
                # Construction history inherited from collection
                # This enables a selective export of nodes
                # relevant to this particular plug-in.
                constructionHistory=False,
                channels=False,
                constraints=False,
                expressions=False,
            )

        packager.add_data({
            "entryFileName": entry_file,
        })

        self.log.info("Extracted {name} to {path}".format(
            name=self.data["subset"],
            path=entry_path)
        )
Ejemplo n.º 3
0
    def process(self, instance):
        from maya import cmds
        from reveries import utils
        from reveries.maya import xgen, capsule, utils as maya_utils

        staging_dir = utils.stage_dir()

        # Export preset
        # (NOTE) Saving as ext `.ma` instead of `.xgip` is because
        #        I'd like to use reference to load it later.
        #        Referencing file that was not `.ma`, `.mb` or other
        #        normal ext will crash Maya on file saving.
        filename = "%s.ma" % instance.data["subset"]
        linkfile = "%s.json" % instance.data["subset"]
        outpath = "%s/%s" % (staging_dir, filename)
        linkpath = "%s/%s" % (staging_dir, linkfile)

        instance.data["repr.XGenInteractive._stage"] = staging_dir
        instance.data["repr.XGenInteractive._files"] = [filename, linkfile]
        instance.data["repr.XGenInteractive.entryFileName"] = filename
        instance.data["repr.XGenInteractive.linkFname"] = linkfile

        child_instances = instance.data.get("childInstances", [])
        try:
            texture = next(chd for chd in child_instances
                           if chd.data["family"] == "reveries.texture")
        except StopIteration:
            file_node_attrs = dict()
        else:
            file_node_attrs = texture.data.get("fileNodeAttrs", dict())

        bound_map = dict()
        clay_shader = "initialShadingGroup"
        descriptions = instance.data["igsDescriptions"]
        with capsule.assign_shader(descriptions, shadingEngine=clay_shader):

            for description in descriptions:

                desc_id = maya_utils.get_id(description)

                # Get bounded meshes
                bound_map[desc_id] = list()
                for mesh in xgen.interactive.list_bound_meshes(description):
                    transform = cmds.listRelatives(mesh,
                                                   parent=True,
                                                   fullPath=True)
                    id = maya_utils.get_id(transform[0])
                    bound_map[desc_id].append(id)

            # (NOTE) Separating grooms and bounding meshes seems not able to
            #        preserve sculpt layer data entirely correct.
            #        For example, sculpting long hair strands to really short,
            #        may ends up noisy shaped after import back.
            #
            #        So now we export the grooms with bound meshes...
            #
            # io.export_xgen_IGS_presets(descriptions, outpath)

            with contextlib.nested(
                    capsule.no_display_layers(instance[:]),
                    # Change to published path
                    capsule.attribute_values(file_node_attrs),
                    capsule.maintained_selection(),
            ):
                cmds.select(descriptions)

                cmds.file(outpath,
                          force=True,
                          typ="mayaAscii",
                          exportSelected=True,
                          preserveReferences=False,
                          channels=True,
                          constraints=True,
                          expressions=True,
                          constructionHistory=True)

        # Parse preset bounding map

        with open(linkpath, "w") as fp:
            json.dump(bound_map, fp, ensure_ascii=False)
    def extract_XGenInteractive(self, packager):
        from maya import cmds

        package_dir = packager.create_package()

        bound_map = dict()
        clay_shader = "initialShadingGroup"
        descriptions = self.data["igsDescriptions"]
        with capsule.assign_shader(descriptions, shadingEngine=clay_shader):

            for description in descriptions:

                desc_id = utils.get_id(description)

                # Get bounded meshes
                bound_map[desc_id] = list()
                for mesh in xgen.interactive.list_bound_meshes(description):
                    transform = cmds.listRelatives(mesh, parent=True)
                    id = utils.get_id(transform[0])
                    bound_map[desc_id].append(id)

            # Export preset
            # (NOTE) Saving as ext `.ma` instead of `.xgip` is because
            #        I'd like to use reference to load it later.
            #        Referencing file that was not `.ma`, `.mb` or other
            #        normal ext will crash Maya on file saving.
            entry_file = packager.file_name("ma")
            entry_path = os.path.join(package_dir, entry_file)

            # (NOTE) Separating grooms and bounding meshes seems not able to
            #        preserve sculpt layer data entirely correct.
            #        For example, sculpting long hair strands to really short,
            #        may ends up noisy shaped after import back.
            #
            #        So now we export the grooms with bound meshes...
            #
            # io.export_xgen_IGS_presets(descriptions, entry_path)

            with contextlib.nested(
                    capsule.no_display_layers(self.member),
                    capsule.maintained_selection(),
            ):
                cmds.select(descriptions)

                cmds.file(entry_path,
                          force=True,
                          typ="mayaAscii",
                          exportSelected=True,
                          preserveReferences=False,
                          channels=True,
                          constraints=True,
                          expressions=True,
                          constructionHistory=True)

        # Parse preset bounding map
        link_file = packager.file_name("json")
        link_path = os.path.join(package_dir, link_file)

        with open(link_path, "w") as fp:
            json.dump(bound_map, fp, ensure_ascii=False)

        packager.add_data({
            "linkFname": link_file,
            "entryFileName": entry_file,
        })
Ejemplo n.º 5
0
    def extract_mayaBinary(self):
        entry_file = self.file_name("mb")
        package_path = self.create_package()
        entry_path = os.path.join(package_path, entry_file)

        mesh_nodes = cmds.ls(self.member,
                             type="mesh",
                             noIntermediate=True,
                             long=True)
        clay_shader = "initialShadingGroup"

        # Hash model and collect Avalon UUID
        geo_id_and_hash = dict()
        hasher = utils.MeshHasher()
        for mesh in mesh_nodes:
            # Get ID
            transform = cmds.listRelatives(mesh, parent=True, fullPath=True)[0]
            id = utils.get_id(transform)
            hasher.set_mesh(mesh)
            hasher.update_points()
            hasher.update_normals()
            hasher.update_uvmap()
            # It must be one mesh paring to one transform.
            geo_id_and_hash[id] = hasher.digest()
            hasher.clear()

        self.add_data({"modelProfile": geo_id_and_hash})

        # Perform extraction
        self.log.info("Extracting %s" % str(self.member))
        cmds.select(self.member, noExpand=True)

        with contextlib.nested(
            capsule.assign_shader(mesh_nodes, shadingEngine=clay_shader),
            capsule.undo_chunk_when_no_undo(),
        ):
            # Remove mesh history, for removing all intermediate nodes
            transforms = cmds.ls(self.member, type="transform")
            cmds.delete(transforms, constructionHistory=True)
            # Remove all stray shapes, ensure no intermediate nodes
            all_meshes = set(cmds.ls(self.member, type="mesh", long=True))
            cmds.delete(list(all_meshes - set(mesh_nodes)))

            cmds.file(
                entry_path,
                force=True,
                typ="mayaBinary",
                exportSelected=True,
                preserveReferences=False,
                # Shader assignment is the responsibility of
                # riggers, for animators, and lookdev, for
                # rendering.
                shader=False,
                # Construction history inherited from collection
                # This enables a selective export of nodes
                # relevant to this particular plug-in.
                constructionHistory=False
            )

        self.add_data({
            "entryFileName": entry_file,
        })

        self.log.info("Extracted {name} to {path}".format(
            name=self.data["subset"],
            path=entry_path)
        )