Replace dasher-pack with unified animation-pack using original Blender bone names
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user