Add AIServer, character art pipeline, and Art package boot integration.
Bring in MaleExplorer assets/shaders, model tooling and Hunyuan updates, plus boot/YooAsset Art package support. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""ModelTranslator CLI:FBX -> 纯模型 FBX + XPbr 贴图 + Unity .mat/.meta。
|
||||
用法:python model_translator.py src/tong.fbx [-o out] [--max-size 2048] [--blender exe]
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import unity_assets as ua
|
||||
from mt_run import HERE, find_blender, run_blender_script
|
||||
|
||||
|
||||
def write_unity_assets(outdir, summary, max_size):
|
||||
remaps = []
|
||||
for m in summary["materials"]:
|
||||
base_png = os.path.join(outdir, m["base_png"])
|
||||
mix_png = os.path.join(outdir, m["mix_png"])
|
||||
base_guid = ua.guid_for(base_png)
|
||||
mix_guid = ua.guid_for(mix_png)
|
||||
alpha_test = m["alpha_mode"] == "transparency"
|
||||
with open(base_png + ".meta", "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(
|
||||
ua.texture_meta(
|
||||
base_guid,
|
||||
srgb=True,
|
||||
max_size=max_size,
|
||||
alpha_is_transparency=alpha_test,
|
||||
)
|
||||
)
|
||||
with open(mix_png + ".meta", "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(ua.texture_meta(mix_guid, srgb=False, max_size=max_size))
|
||||
|
||||
mat_name = (
|
||||
summary["model"]
|
||||
if m["safe_name"] == summary["model"]
|
||||
else "%s_%s" % (summary["model"], m["safe_name"])
|
||||
)
|
||||
mat_path = os.path.join(outdir, mat_name + ".mat")
|
||||
mat_guid = ua.guid_for(mat_path)
|
||||
with open(mat_path, "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(
|
||||
ua.material_yaml(
|
||||
mat_name, ua.XPBR_SHADER_GUID, base_guid, mix_guid, alpha_test
|
||||
)
|
||||
)
|
||||
with open(mat_path + ".meta", "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(ua.material_meta(mat_guid))
|
||||
remaps.append((m["name"], mat_guid))
|
||||
|
||||
fbx_path = os.path.join(outdir, summary["fbx"])
|
||||
fbx_guid = ua.guid_for(fbx_path)
|
||||
with open(fbx_path + ".meta", "w", encoding="utf-8", newline="\n") as f:
|
||||
f.write(ua.model_meta(fbx_guid, remaps))
|
||||
return {
|
||||
"fbx": fbx_path,
|
||||
"fbx_guid": fbx_guid,
|
||||
"materials": remaps,
|
||||
"outdir": outdir,
|
||||
}
|
||||
|
||||
|
||||
def report(summary, outdir):
|
||||
print("== %s -> %s" % (summary["model"], outdir))
|
||||
for m in summary["materials"]:
|
||||
print(
|
||||
" 材质 %-24s A通道=%s 尺寸=%dx%d"
|
||||
% (m["name"], m["alpha_mode"], m["size"][0], m["size"][1])
|
||||
)
|
||||
for k, v in m["sources"].items():
|
||||
print(" %-10s %s" % (k, v or "(常量)"))
|
||||
for w in m["warnings"]:
|
||||
print(" [警告] %s" % w)
|
||||
|
||||
|
||||
def translate_fbx(src, outdir, max_size=2048, blender=None):
|
||||
"""Convert bake-output FBX (+ sibling PBR maps) into XPbr assets. Returns summary dict."""
|
||||
blender_exe = find_blender(blender)
|
||||
os.makedirs(outdir, exist_ok=True)
|
||||
summary = run_blender_script(
|
||||
blender_exe, "bl_convert.py", [src, outdir, str(max_size)]
|
||||
)
|
||||
unity = write_unity_assets(outdir, summary, max_size)
|
||||
return {**summary, "unity": unity}
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument("input", help="FBX 文件或目录")
|
||||
ap.add_argument("-o", "--out", default=os.path.join(HERE, "out_xpbr"))
|
||||
ap.add_argument("--max-size", type=int, default=2048)
|
||||
ap.add_argument("--blender", default=None)
|
||||
args = ap.parse_args()
|
||||
|
||||
if os.path.isdir(args.input):
|
||||
srcs = [
|
||||
os.path.join(args.input, f)
|
||||
for f in sorted(os.listdir(args.input))
|
||||
if f.lower().endswith(".fbx")
|
||||
]
|
||||
if not srcs:
|
||||
sys.exit("目录中没有 FBX:%s" % args.input)
|
||||
else:
|
||||
srcs = [args.input]
|
||||
|
||||
for src in srcs:
|
||||
name = os.path.splitext(os.path.basename(src))[0]
|
||||
outdir = os.path.join(args.out, name)
|
||||
summary = translate_fbx(src, outdir, args.max_size, args.blender)
|
||||
report(summary, outdir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user