"""Controlled local-influence cleanup of TokenRig-41 hand weights only.""" import json import sys from pathlib import Path import bpy folder=Path(sys.argv[sys.argv.index('--')+1]) bpy.ops.wm.open_mainfile(filepath=str(folder/'tokenrig_mixamo41.blend')) arm=next(o for o in bpy.context.scene.objects if o.type=='ARMATURE') mesh=next(o for o in bpy.context.scene.objects if o.type=='MESH') height=max((mesh.matrix_world@v.co).z for v in mesh.data.vertices) changes=[] for v in mesh.data.vertices: p=mesh.matrix_world@v.co if not (abs(p.x)>height*.255 and height*.550 else 'Right' old={mesh.vertex_groups[g.group].name:g.weight for g in v.groups} allowed={n:w for n,w in old.items() if n in (f'mixamorig:{side}Arm',f'mixamorig:{side}ForeArm') or n.startswith(f'mixamorig:{side}Hand')} total=sum(allowed.values()) rejected=sum(w for n,w in old.items() if n not in allowed) assert total>1e-8 for g in list(v.groups): mesh.vertex_groups[g.group].remove([v.index]) for n,w in allowed.items(): mesh.vertex_groups[n].add([v.index],w/total,'REPLACE') if rejected>.001: changes.append({'vertex':v.index,'removed':rejected,'old':old}) (folder/'local_cleanup.json').write_text(json.dumps({'method':'CampGuide-specific T-pose hand-region whitelist; same-side Arm/ForeArm/Hand/fingers only; renormalize; no reference weights', 'changed_vertices_over_0_001':len(changes),'changes':changes},indent=2),encoding='utf-8') bpy.ops.wm.save_as_mainfile(filepath=str(folder/'tokenrig_mixamo41_local.blend'),compress=True) bpy.ops.export_scene.gltf(filepath=str(folder/'tokenrig_mixamo41_local.glb'),export_format='GLB',export_skins=True,export_animations=False,export_def_bones=False) print('LOCAL_CLEANUP',len(changes))