Files
animation/characters/female/lena_nude/hires_claude/16b_images.py
T
jeremy 3ba86b2ea8 feat: clothing lane, character sources, and DCC bridges
Bulk import of the working lanes that were living untracked on the PC.

Content:
- characters/  Lena/male body lanes, bakes, texture work, run logs
- clothing/    garment pipeline, configs, gates, contract docs
- garments/    MD-authored garment sources (.zprj/.zpac)
- UAL-Lib/     Universal Animation Library 2 source (.blend/.fbx/.glb)
- tools/       blender_bridge, iclone_bridge, md_bridge, tailor, glm_agent
- docs/, plans/, dev/, .agents/plans/

Repo hygiene:
- .gitattributes: LFS now covers .blend, .zprj, .zpac, .obj, .npy and the
  Reallusion .iAvatar/.ccAvatar/.ccRestore containers. Without this the
  ~3.8 GB in this commit would land as raw blobs. .png/.jpg are left out
  on purpose — ~250 are already tracked raw and converting them would
  rewrite every one without shrinking history.
- .gitignore: exclude /accurig/ (~1 GB AccuRig program files, redistributable
  from Reallusion, nothing authored here) and /dev/null/ (git-lfs hook copies
  dropped by a `>/dev/null` redirect on Windows).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 15:55:43 -07:00

46 lines
2.2 KiB
Python

# Which image datablocks exist, and which ones the body material actually SAMPLES.
# blender --background --python 16b_images.py -- <blend> [<blend2> ...]
import bpy, sys
import numpy as np
for BLEND in sys.argv[sys.argv.index("--") + 1:]:
bpy.ops.wm.open_mainfile(filepath=BLEND)
print(f"\n===== {BLEND} =====")
ob = max([o for o in bpy.data.objects if o.type == 'MESH'],
key=lambda o: len(o.data.vertices))
print(f"body '{ob.name}' {len(ob.data.vertices)}v materials="
f"{[ms.material.name if ms.material else None for ms in ob.material_slots]}")
for i in bpy.data.images:
b = np.empty(i.size[0] * i.size[1] * 4, dtype=np.float32)
try:
i.pixels.foreach_get(b)
m = b.reshape(-1, 4)[:, :3]
stat = f"mean {m.mean(axis=0).round(4)} std {m.std(axis=0).round(4)}"
except Exception as e:
stat = f"(no pixels: {e})"
print(f" IMG '{i.name}' {i.size[0]}x{i.size[1]} packed={bool(i.packed_file)} "
f"file='{i.filepath}' {stat}")
for ms in ob.material_slots:
mat = ms.material
if not mat or not mat.node_tree:
continue
print(f" MAT '{mat.name}':")
bsdf = next((n for n in mat.node_tree.nodes if n.type == 'BSDF_PRINCIPLED'), None)
for n in mat.node_tree.nodes:
if n.type == 'TEX_IMAGE':
tgt = []
for o in n.outputs:
for lk in o.links:
tgt.append(f"{lk.to_node.name}.{lk.to_socket.name}")
print(f" TEX_IMAGE node '{n.name}' image='{n.image.name if n.image else None}'"
f" -> {tgt if tgt else 'UNCONNECTED'}")
if bsdf:
for sock in ("Base Color", "Normal", "Roughness", "Metallic"):
if sock in bsdf.inputs:
lk = bsdf.inputs[sock].links
src = lk[0].from_node.name if lk else "(unlinked)"
if lk and lk[0].from_node.type == 'TEX_IMAGE':
src += f" image='{lk[0].from_node.image.name if lk[0].from_node.image else None}'"
print(f" BSDF.{sock} <- {src}")
print("IMAGES_DONE")