91 lines
2.4 KiB
Python
91 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Rename rig root node in character GLBs to 'Character' for consistent paths.
|
|
|
|
This must run before Godot imports the GLBs. It modifies the .glb JSON to rename
|
|
the rig root node (oldpop-rig, bob-rig, etc.) to 'Character' so all characters
|
|
share the same skeleton path: Character/Skeleton3D:bone_name
|
|
|
|
Backups are created as .glb.bak on first run.
|
|
|
|
Re-runnable: if backup exists, restore from backup first to ensure idempotency.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import struct
|
|
import shutil
|
|
import sys
|
|
|
|
CHARACTERS = {
|
|
'Bob.glb': 'bob-rig',
|
|
'Oldpop.glb': 'oldpop-rig',
|
|
'Masbro.glb': 'masbro-tpose',
|
|
'Gatot.glb': 'gatot-tpose',
|
|
}
|
|
NEW_NAME = 'Character'
|
|
CHARS_DIR = os.path.join(os.path.dirname(__file__), '..', 'assets', 'characters')
|
|
|
|
|
|
def find_rig_node(nodes, old_name):
|
|
for i, n in enumerate(nodes):
|
|
if n.get('name') == old_name:
|
|
return i
|
|
return -1
|
|
|
|
|
|
def process_glb(path, old_name):
|
|
backup = path + '.bak'
|
|
if os.path.exists(backup):
|
|
shutil.copy(backup, path)
|
|
else:
|
|
shutil.copy(path, backup)
|
|
|
|
with open(path, 'rb') as f:
|
|
f.read(12) # magic + version + length
|
|
chunk_len = struct.unpack('<I', f.read(4))[0]
|
|
f.read(4) # chunk type
|
|
json_data = f.read(chunk_len)
|
|
rest = f.read()
|
|
|
|
data = json.loads(json_data)
|
|
nodes = data.get('nodes', [])
|
|
|
|
idx = find_rig_node(nodes, old_name)
|
|
if idx < 0:
|
|
print(f' {os.path.basename(path)}: rig root "{old_name}" NOT FOUND, skipping')
|
|
return False
|
|
|
|
nodes[idx]['name'] = NEW_NAME
|
|
|
|
new_json = json.dumps(data, separators=(',', ':')).encode('utf-8')
|
|
new_chunk_len = len(new_json)
|
|
new_length = 12 + 8 + new_chunk_len + len(rest)
|
|
|
|
with open(path, 'wb') as f:
|
|
f.write(b'glTF')
|
|
f.write(struct.pack('<I', 2))
|
|
f.write(struct.pack('<I', new_length))
|
|
f.write(struct.pack('<I', new_chunk_len))
|
|
f.write(b'JSON')
|
|
f.write(new_json)
|
|
f.write(rest)
|
|
|
|
print(f' {os.path.basename(path)}: renamed {old_name} -> {NEW_NAME}')
|
|
return True
|
|
|
|
|
|
def main():
|
|
os.chdir(CHARS_DIR)
|
|
print(f'Processing GLBs in {CHARS_DIR}')
|
|
for glb, old_name in CHARACTERS.items():
|
|
path = os.path.join(CHARS_DIR, glb)
|
|
if not os.path.exists(path):
|
|
print(f' {glb}: not found, skipping')
|
|
continue
|
|
process_glb(path, old_name)
|
|
print('Done.')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|