88 lines
4.9 KiB
Python
88 lines
4.9 KiB
Python
# 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 :
|
|
# <Nom>_Cap : emplacements listes dans cap= (calotte) ; opacite cap_opacity= ou "white" (calotte opaque)
|
|
# <Nom>_Strands : tous les autres emplacements (meches) ; opacite strands_opacity=
|
|
# Controle final : dependances du SkeletalMesh (squelette et ces deux materiaux seulement).
|
|
#
|
|
# Usage :
|
|
# UnrealEditor-Cmd.exe <projet> -run=pythonscript "-script=<projet>/Tools/HairMaterials.py mesh=/Game/Heavy/New5/Hairs/Nom
|
|
# diffuse=<couleur.png> strands_opacity=<masque.jpg> 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=<fichier> strands_opacity=<fichier> [cap_opacity=<fichier>|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"))
|