""" OBSOLETE: Placeholder body type GLBs (workaround for failed bone-scaling approach). This script was a stopgap to produce placeholder body type files with blue material tinting after create_body_types.py produced broken meshes. No longer needed -- the body type pipeline will use hand-authored meshes instead. Preserved as documentation only. Run via: tooling/blender --background --python \\ spikes/quaternius-aesthetic/scripts/blender/create_placeholder_bodies.py \\ -- """ import bpy import sys import os argv = sys.argv argv = argv[argv.index("--") + 1:] if "--" in argv else [] if len(argv) < 2: print("Usage: -- ") sys.exit(1) INPUT_DIR = argv[0] OUTPUT_DIR = argv[1] os.makedirs(OUTPUT_DIR, exist_ok=True) MALE_GLTF = os.path.join(INPUT_DIR, "Superhero_Male_FullBody.gltf") FEMALE_GLTF = os.path.join(INPUT_DIR, "Superhero_Female_FullBody.gltf") PLACEHOLDER_COLOR = (0.2, 0.35, 0.65, 1.0) # muted blue # muscular keeps original textures (it IS the Superhero base) # all others get blue placeholder material VARIANTS = [ ("male_thin", MALE_GLTF, True), ("male_average", MALE_GLTF, True), ("male_muscular", MALE_GLTF, False), # keep original ("male_heavy", MALE_GLTF, True), ("female_thin", FEMALE_GLTF, True), ("female_average", FEMALE_GLTF, True), ("female_muscular", FEMALE_GLTF, False), # keep original ("female_heavy", FEMALE_GLTF, True), ("child", FEMALE_GLTF, True), ] print("=== Create placeholder body types ===") def clear_scene(): bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete() for c in list(bpy.data.collections): bpy.data.collections.remove(c) def apply_placeholder_material(obj): """Replace all materials with solid blue placeholder.""" if obj.type != 'MESH': return # Create placeholder material mat = bpy.data.materials.new(name="placeholder_blue") mat.use_nodes = True bsdf = mat.node_tree.nodes.get("Principled BSDF") if bsdf: bsdf.inputs["Base Color"].default_value = PLACEHOLDER_COLOR bsdf.inputs["Roughness"].default_value = 1.0 bsdf.inputs["Metallic"].default_value = 0.0 # Clear existing materials and assign placeholder obj.data.materials.clear() obj.data.materials.append(mat) for variant_name, source_gltf, is_placeholder in VARIANTS: print(f"\n {variant_name}...") clear_scene() if not os.path.exists(source_gltf): print(f" SKIP: source not found: {source_gltf}") continue bpy.ops.import_scene.gltf(filepath=source_gltf) objects = list(bpy.data.objects) # Apply placeholder material to placeholder variants only if is_placeholder: for obj in objects: if obj.type == 'MESH': apply_placeholder_material(obj) # Select all for export bpy.ops.object.select_all(action='SELECT') if objects: bpy.context.view_layer.objects.active = objects[0] output_path = os.path.join(OUTPUT_DIR, f"{variant_name}.glb") bpy.ops.export_scene.gltf( filepath=output_path, export_format='GLB', use_selection=True, export_apply=False, export_animations=False, export_skins=True, ) size_kb = os.path.getsize(output_path) // 1024 print(f" Exported: {variant_name}.glb ({size_kb} KB)") print("\n=== Done ===") for name, _, _ in VARIANTS: path = os.path.join(OUTPUT_DIR, f"{name}.glb") status = "[OK]" if os.path.exists(path) else "[MISSING]" print(f" {status} {name}.glb")