"""Gripper parts as separate (unjoined) GLB nodes, each mesh scrubbed clean for Blender glTF import.
(Superseded in the daily loop by gen_gripper_urdf.py's GLB rebuild — kept for re-seeding from raw STLs.)"""
import numpy as np, trimesh
import gripper_gen as g
S = 10.0; zf = g.GRIP_GAP / 2.0
def clean(m):
    for fn in (lambda: m.merge_vertices(),
               lambda: m.update_faces(m.nondegenerate_faces()),
               lambda: m.update_faces(m.unique_faces()),
               lambda: m.remove_unreferenced_vertices(),
               lambda: m.fix_normals()):
        try: fn()
        except Exception: pass
    return m
# split thumb: horn_mount (attaches to servo) + finger (editable)
clean(trimesh.boolean.union([g._horn_plate(), g._box(-36, -15, g.FY0, g.FY0 + 4, zf, 11)], engine="manifold")).export("horn_mount.stl")
prof = g._finray_profile(g.FINGER_LEN, g.FR_H, g.FR_WALL, g.FR_RIBS)
fr = trimesh.creation.extrude_polygon(prof, g.FY1 - g.FY0)
fr.apply_transform(np.array([[-1, 0, 0, g.ROOT_X], [0, 0, 1, g.FY0], [0, 1, 0, zf], [0, 0, 0, 1]], float))
clean(fr).export("finger.stl")
scene = trimesh.Scene()
for name, fn in [("servo", "st3215.stl"), ("holder", "holder_approx_drilled.stl"), ("horn_mount", "horn_mount.stl"), ("finger", "finger.stl"), ("fixed_jaw", "fixed_jaw.stl")]:
    m = clean(trimesh.load(fn, force="mesh").copy()); m.apply_scale(0.001 * S)
    scene.add_geometry(m, node_name=name, geom_name=name)
scene.export("gripper.glb")
print("wrote gripper.glb nodes: servo, holder, horn_mount, finger, fixed_jaw (all separate)")
