# Protocole de conversion d'une coiffure (Docs/Migration/13_Protocole_Coiffure.md), etape 4 : textures et materiaux. # # Importe les textures de la coiffure, cree deux materiaux enfants de /Game/Heavy/Daz/Bridget/Hairs/DazHair (le # materiau des coiffures Daz : parametres HairColor et HairThickness pilotes par le jeu) et les affecte aux # emplacements du SkeletalMesh produit par LPHairFromStaticMesh : # _Cap : emplacements listes dans cap= (calotte) ; opacite cap_opacity= ou "white" (calotte opaque) # _Strands : tous les autres emplacements (meches) ; opacite strands_opacity= # Controle final : dependances du SkeletalMesh (squelette et ces deux materiaux seulement). # # Usage : # UnrealEditor-Cmd.exe -run=pythonscript "-script=/Tools/HairMaterials.py mesh=/Game/Heavy/New5/Hairs/Nom # diffuse= strands_opacity= cap_opacity=white cap=Hair_Base [thicken=1]" -unattended -nopause -nosplash # Les fichiers de textures sont des chemins sur disque ; les textures sont creees a cote du SkeletalMesh. # Sortie : lignes "HAIRMAT" du journal. import os import sys import unreal eal = unreal.EditorAssetLibrary mel = unreal.MaterialEditingLibrary tools = unreal.AssetToolsHelpers.get_asset_tools() args = dict(a.split("=", 1) for a in sys.argv[1:] if "=" in a) def import_texture(file, folder, name): task = unreal.AssetImportTask() task.filename = file.replace("\\", "/") task.destination_path = folder task.destination_name = name task.automated = True task.replace_existing = True task.save = True tools.import_asset_tasks([task]) return unreal.load_asset(folder + "/" + name) def make_mic(folder, name, parent, diffuse, opacity, thicken): path = folder + "/" + name mic = unreal.load_asset(path) if eal.does_asset_exist(path) else tools.create_asset( name, folder, unreal.MaterialInstanceConstant, unreal.MaterialInstanceConstantFactoryNew()) mel.set_material_instance_parent(mic, parent) mel.set_material_instance_texture_parameter_value(mic, "MapDiffuse", diffuse) mel.set_material_instance_texture_parameter_value(mic, "MapOpacity", opacity) mel.set_material_instance_scalar_parameter_value(mic, "Thicken", thicken) mel.update_material_instance(mic) eal.save_loaded_asset(mic, only_if_is_dirty=False) return mic mesh_path = args.get("mesh") if not mesh_path or not args.get("diffuse") or not args.get("strands_opacity"): unreal.log_error("HAIRMAT usage : mesh=/Game/... diffuse= strands_opacity= [cap_opacity=|white] [cap=Slot1,Slot2] [thicken=1]") else: folder, name = mesh_path.rsplit("/", 1) thicken = float(args.get("thicken", "1")) cap_slots = [s for s in args.get("cap", "").split(",") if s] parent = unreal.load_asset("/Game/Heavy/Daz/Bridget/Hairs/DazHair") diffuse = import_texture(args["diffuse"], folder, name + "_Diffuse") strands_opacity = import_texture(args["strands_opacity"], folder, name + "_StrandsOpacity") strands = make_mic(folder, name + "_Strands", parent, diffuse, strands_opacity, thicken) # Calotte : seulement si un emplacement lui est attribue (Pocolov 11 : emplacement unique, pas de calotte). cap = None if cap_slots: cap_arg = args.get("cap_opacity", "white") cap_opacity = unreal.load_asset("/Engine/EngineResources/WhiteSquareTexture") if cap_arg == "white" else import_texture(cap_arg, folder, name + "_CapOpacity") cap = make_mic(folder, name + "_Cap", parent, diffuse, cap_opacity, 1.0) # Affectation : modifier les elements puis reaffecter le tableau entier et sauvegarder sans condition # (une affectation Python ne marque pas l'asset modifie). mesh = unreal.load_asset(mesh_path) materials = [] used = set() for slot in mesh.get_editor_property("materials"): slot_name = str(slot.get_editor_property("material_slot_name")) slot.set_editor_property("material_interface", cap if slot_name in cap_slots else strands) materials.append(slot) used.add(folder + "/" + (cap if slot_name in cap_slots else strands).get_name()) unreal.log_warning("HAIRMAT emplacement %s -> %s" % (slot_name, (cap if slot_name in cap_slots else strands).get_name())) mesh.set_editor_property("materials", materials) eal.save_loaded_asset(mesh, only_if_is_dirty=False) registry = unreal.AssetRegistryHelpers.get_asset_registry() registry.scan_modified_asset_files([unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_content_dir()) + mesh_path[len("/Game/"):] + ".uasset"]) options = unreal.AssetRegistryDependencyOptions(include_soft_package_references=True, include_hard_package_references=True) deps = [str(d) for d in registry.get_dependencies(mesh_path, options) if not str(d).startswith("/Script/")] expected = {mesh_path + "_Skeleton"} | used unreal.log_warning("HAIRMAT dependances de %s : %s -> %s" % (name, deps, "OK" if set(deps) == expected else "A VERIFIER"))