Files
AIGame/Tools/greathorn_studio_finish.py

53 lines
3.7 KiB
Python

"""Offline packaging/skin transfer of the Studio trial; preserve original finished animations."""
import argparse,hashlib,json,shutil,subprocess,sys
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1]
OUT=ROOT/'Tools/output/enemy_studio_trial/GreatHorn'
ASSET='Assets/Bundles/Characters/Enemy/GreatHornStudio'
BLENDER='D:/Tools/Blender/blender-5.0.0-windows-x64/blender.exe'
sys.path.insert(0,str(ROOT/'Tools/model_tools'))
from mt_run import run_blender_script
sys.path.insert(0,str(ROOT/'Tools'))
from enemy_character_pipeline import unity,script,wait_editor
def blender(file,args,log):
with (OUT/log).open('w',encoding='utf-8') as f:
subprocess.run([BLENDER,'-b','-t','1','--factory-startup','--python',str(ROOT/'Tools/model_tools'/file),'--',*map(str,args)],stdout=f,stderr=subprocess.STDOUT,timeout=600,check=True)
def main():
parser=argparse.ArgumentParser();parser.add_argument('--play-check',action='store_true');args=parser.parse_args()
receipt=json.loads((OUT/'trial.json').read_text(encoding='utf-8'))
assert receipt['status'] in ('mesh_ready','edit_validated','validated')
for relative,digest in receipt['originals'].items():assert hashlib.sha256((ROOT/relative).read_bytes()).hexdigest()==digest,relative+' changed'
blender('bl_prepare_studio_trial.py',[OUT],'static_export.log')
result=run_blender_script(BLENDER,'bl_convert.py',[str(OUT/'static/GreatHornStudio.fbx'),str(OUT/'xpbr'),'1024'])
(OUT/'xpbr.json').write_text(json.dumps(result,indent=2),encoding='utf-8')
print('XPbr packaging complete',flush=True)
blender('bl_transfer_skin.py',[ROOT/'Tools/output/enemy_dgx/GreatHorn/high_rig/rigged.glb',OUT/'xpbr/GreatHornStudio.fbx',OUT/'GreatHornStudio_Rigged.fbx','--low-up','Y','--align-bounds'],'skin_transfer.log')
print('Original rig weight transfer complete',flush=True)
unity('set_autotick',enable=True)
if unity('editor_status')['playMode']!='stopped':raise RuntimeError('Editor is in Play; offline trial is ready, import after it stops')
for name in ['GreatHornStudio.fbx','GreatHornStudio_base.png','GreatHornStudio_mix.png']:
unity('import_asset',source=str(OUT/'xpbr'/name),path=ASSET+'/'+name,confirm=True)
unity('import_asset',source=str(OUT/'GreatHornStudio_Rigged.fbx'),path=ASSET+'/Rigged/GreatHornStudio_Rigged.fbx',confirm=True)
script('SetupCharacter','SetupCharacter.Run',['Enemy','GreatHornStudio',.8])
script('GreatHornStudioTrial','GreatHornStudioTrial.Prepare',[])
script('GreatHornStudioTrial','GreatHornStudioTrial.ExportFootConstraints',[])
blender('bl_fit_studio_soles.py',[OUT],'sole_fit.log')
unity('import_asset',source=str(OUT/'GreatHornStudio_Rigged.fbx'),path=ASSET+'/Rigged/GreatHornStudio_Rigged.fbx',confirm=True)
script('GreatHornStudioTrial','GreatHornStudioTrial.Build',[])
script('GreatHornStudioTrial','GreatHornStudioTrial.BuildReview',[])
script('GreatHornStudioTrial','GreatHornStudioTrial.Capture',[])
receipt['status']='edit_validated'
if args.play_check:
unity('editor_play')
try:
wait_editor('playing');script('GreatHornStudioTrial','GreatHornStudioTrial.Play',[]);receipt['status']='validated'
finally:unity('editor_stop');wait_editor('stopped')
for relative,digest in receipt['originals'].items():assert hashlib.sha256((ROOT/relative).read_bytes()).hexdigest()==digest,relative+' changed'
receipt.update(soleFit=json.loads((OUT/'sole_fit.json').read_text(encoding='utf-8')),riggedSha256=hashlib.sha256((OUT/'GreatHornStudio_Rigged.fbx').read_bytes()).hexdigest(),originalResourcesUnchanged=True)
(OUT/'trial.json').write_text(json.dumps(receipt,indent=2),encoding='utf-8')
if __name__=='__main__':main()