53 lines
3.7 KiB
Python
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()
|