def extract_XGenLegacy(self, packager): packager.skip_stage() package_dir = packager.create_package() xgen_files = list() descriptions_data = dict() for desc in self.data["xgenDescriptions"]: palette = xgen.get_palette_by_description(desc) # Save UUID and bounding descriptions_data[desc] = { "id": utils.get_id(desc), "bound": xgen.list_bound_geometry(desc), } # Transfer maps maps = xgen.maps_to_transfer(desc) data_paths = xgen.current_data_paths(palette, expand=True) for src in maps: for root in data_paths: if src.startswith(root): # At least one root will be matched, since all # map path has been validated that must exists # under ${DESC} dir. tail = src[len(root):] if tail.startswith("/") or tail.startswith("\\"): tail = tail[1:] break else: self.log.critical("Searched data path:") for root in data_paths: self.log.critical(root) raise Exception("Could not find root path for %s , " "this is a bug." % src) dst = os.path.join(package_dir, "maps", palette, tail) packager.add_file(src, dst) # Export guides guides = xgen.list_guides(desc) if guides: guide_file = os.path.join(package_dir, "guides", palette, desc + ".abc") io.export_xgen_LGC_guides(guides, guide_file) # Export grooming groom = xgen.get_groom(desc) if groom and cmds.objExists(groom): groom_dir = os.path.join(package_dir, "groom", palette, desc) xgen.export_grooming(desc, groom, groom_dir) # Extract palette for palette in self.data["xgenPalettes"]: xgen_file = palette + ".xgen" xgen_path = os.path.join(package_dir, xgen_file) io.export_xgen_LGC_palette(palette, xgen_path) xgen_files.append(xgen_file) # Culled xgd_file = palette + "_culled.xgd" xgd_path = os.path.join(package_dir, "deltas", palette, xgd_file) if xgen.save_culled_as_delta(palette, xgd_path): self.log.info("Culled primitives saved.") packager.add_data({ "entryFileName": None, # Yes, no entry file for XGen Legacy. "descriptionsData": descriptions_data, "palettes": xgen_files, "step": self.data["step"], })
def load(self, context, name=None, namespace=None, options=None): # (NOTE) AnimWire modifier has a bug that not able to find wires if # namespace is applied. # The hairSystem is okay to work with, but not able to update # XGen preview. So you either simulate without the update, or # build the simulation without namespace and save with .xgen # file exported, then reference it with namespace. # # https://forums.autodesk.com/t5/maya-dynamics/anim-wire- # errors-when-using-namespaces/m-p/7329883#M5642 # if not cmds.pluginInfo("xgenToolkit", query=True, loaded=True): cmds.loadPlugin("xgenToolkit", quiet=True) representation = context["representation"] asset = context["asset"] asset_name = asset["data"].get("shortName", asset["name"]) family_name = context["version"]["data"]["families"][0].split(".")[-1] namespace = namespace or unique_root_namespace(asset_name, family_name) descriptions_data = representation["data"]["descriptionsData"] baked = representation["data"]["step"] != xgen.SHAPING bound_meshes = list() # Varify selection selected = cmds.ls(sl=True, long=True) all_bound_geos = set() for data in descriptions_data.values(): for geo in data["bound"]: all_bound_geos.add("|" + geo) msg = ("Require bound geos: {0}\n" "Selected: {1}".format(all_bound_geos, selected)) assert set(selected) == all_bound_geos, msg # Rename bound geos to namespace for node in selected: bound_meshes.append(node) # Copy maps local_map_dir = os.path.join(avalon.api.Session["AVALON_WORKDIR"], "xgen", "published", # Add username to ease out file lock issue getpass.getuser()) map_dir = os.path.join(self.package_path, "maps") for palette in os.listdir(map_dir): palette_dir = os.path.join(map_dir, palette) local_palette_dir = os.path.join(local_map_dir, palette) # Copy copy_tree(palette_dir, local_palette_dir) # Import palette palette_nodes = list() xgen.preview_clear() for file in representation["data"]["palettes"]: xgen_path = os.path.join(self.package_path, file) xgen_path = xgen_path.replace("\\", "/") palette_node = xgen.import_palette(xgen_path, wrapPatches=True) palette_nodes.append(palette_node) # Set xgDataPath palette = os.path.splitext(file)[0] data_path = os.path.join(local_map_dir, palette).replace("\\", "/") xgen.set_data_path(palette_node, data_path) if not baked: # Bind grooming descriptions to geometry for desc in xgen.list_descriptions(palette_node): groom = xgen.get_groom(desc) if groom: groom_dir = os.path.join(self.package_path, "groom", palette_node, desc) xgen.import_grooming(desc, groom, groom_dir) # Apply ID asset_id = str(asset["_id"]) with utils.id_namespace(asset_id): for desc in xgen.list_descriptions(palette_node): _desc = desc.rsplit(":", 1)[-1] id = descriptions_data[_desc]["id"] utils.upsert_id(desc, id) # Ensure tube shade disabled xgen.disable_tube_shade(palette_node) group_name = self.group_name(namespace, name) # Cannot be grouped # cmds.group(palette_nodes, name=group_name, world=True) # palette_nodes = cmds.ls(palette_nodes, long=True) # Containerising.. nodes = palette_nodes[:] nodes += bound_meshes nodes += cmds.listRelatives(palette_nodes, allDescendents=True, fullPath=True) nodes += apply_namespace_wrapper(namespace, nodes) container_id = options.get("containerId", utils.generate_container_id()) container = subset_containerising(name=name, namespace=namespace, container_id=container_id, nodes=nodes, context=context, cls_name=self.__class__.__name__, group_name=group_name) return container
def process(self, instance): from maya import cmds from reveries import utils from reveries.maya import io, utils as maya_utils from reveries.maya.xgen import legacy as xgen staging_dir = utils.stage_dir() files = list() xgen_files = list() descriptions_data = dict() for desc in instance.data["xgenDescriptions"]: palette = xgen.get_palette_by_description(desc) # Save UUID and bounding descriptions_data[desc] = { "id": maya_utils.get_id(desc), "bound": xgen.list_bound_geometry(desc), } # Stage maps map_stage = staging_dir + "/maps/%s" % palette for head, src in xgen.maps_to_transfer(desc): relative = os.path.relpath(src, head) if os.path.isfile(src): relative = os.path.dirname(relative) ship = shutil.copy2 elif os.path.isdir(src): ship = shutil.copytree else: continue dst_dir = map_stage + "/" + relative if not os.path.isdir(dst_dir): os.makedirs(dst_dir) try: ship(src, dst_dir) except OSError: msg = "An unexpected error occurred." self.log.critical(msg) raise OSError(msg) for root, _, fnames in os.walk(map_stage): relative = os.path.relpath(root, staging_dir) relative = "" if relative == "." else (relative + "/") relative = relative.replace("\\", "/") for file in fnames: map_file = relative + file files.append(map_file) # Export guides guides = xgen.list_guides(desc) if guides: guide_file = "guides/%s/%s.abc" % (palette, desc) guide_path = "%s/%s" % (staging_dir, guide_file) io.export_xgen_LGC_guides(guides, guide_path) files.append(guide_file) # Export grooming groom = xgen.get_groom(desc) if groom and cmds.objExists(groom): groom_dir = "groom/%s/%s" % (palette, desc) groom_path = "%s/%s" % (staging_dir, groom_dir) xgen.export_grooming(desc, groom, groom_path) # Walk groom_path and add into files for root, _, fnames in os.walk(groom_path): relative = os.path.relpath(root, staging_dir) relative = "" if relative == "." else (relative + "/") for file in fnames: groom_file = relative + file files.append(groom_file) # Extract palette for palette in instance.data["xgenPalettes"]: xgen_file = palette + ".xgen" xgen_path = "%s/%s" % (staging_dir, xgen_file) io.export_xgen_LGC_palette(palette, xgen_path) xgen_files.append(xgen_file) files.append(xgen_file) # Culled xgd_file = "deltas/%s/%s_culled.xgd" % (palette, palette) xgd_path = "%s/%s" % (staging_dir, xgd_file) if xgen.save_culled_as_delta(palette, xgd_path): self.log.info("Culled primitives saved.") files.append(xgd_file) instance.data["repr.XGenLegacy._stage"] = staging_dir instance.data["repr.XGenLegacy._files"] = files instance.data["repr.XGenLegacy.entryFileName"] = None # no entry file instance.data["repr.XGenLegacy.descriptionsData"] = descriptions_data instance.data["repr.XGenLegacy.palettes"] = xgen_files instance.data["repr.XGenLegacy.step"] = instance.data["step"]