SOURCE / PINNED RELEASE
Made of little things.
Body Journal
- Release
- e8049f8da4e2…
- Author-recorded commit
- 61c04bf0e8aa…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6c4554844c7
Archive hash verified: 4369d778da046a8b…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import { layers, type AnatomyLayer } from './layers.js';
import { anatomyTree, anatomyLeaves, descendants, flattenAnatomy } from './anatomy-tree.js';
export interface InspectionView {
version: 2; layer: AnatomyLayer; target: string | null;
hidden: string[]; yaw: number; pitch: number; distance: number;
}
export interface FocusOption { id: string; label: string }
export function focusCatalog(layer: AnatomyLayer): FocusOption[] {
return flattenAnatomy(anatomyTree(layer)).filter(n => n.id !== 'outline' && n.id !== 'region:body').map(({id,label}) => ({id,label}));
}
export function focusLabel(view: InspectionView): string {
return focusCatalog(view.layer).find(p => p.id === view.target)?.label || 'Whole body';
}
export function hiddenLabels(view: InspectionView): string[] {
const hidden = new Set(view.hidden);
return flattenAnatomy(anatomyTree(view.layer)).filter(n => !n.children && hidden.has(n.id)).map(n => n.label);
}
export function parseInspection(value: unknown, expectedLayer?: AnatomyLayer): InspectionView {
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid inspection view.');
const v = value as Record<string, unknown>;
if ((v.version !== 1 && v.version !== 2) || !layers.includes(v.layer as AnatomyLayer) || (expectedLayer && v.layer !== expectedLayer)) throw new Error('Invalid inspection layer.');
const layer = v.layer as AnatomyLayer;
if (v.target !== null && !focusCatalog(layer).some(p => p.id === v.target)) throw new Error('Unknown inspection target.');
const leaves = anatomyLeaves(anatomyTree(layer)); let hidden: string[];
if (v.version === 1) {
if (!['full','fade','isolate'].includes(String(v.context)) || (v.target === null && v.context !== 'full')) throw new Error('Invalid inspection context.');
const selected = new Set(descendants(layer, v.target as string));
hidden = v.context === 'isolate' ? leaves.filter(id => !selected.has(id)).sort() : [];
} else {
if (v.version !== 2 || !Array.isArray(v.hidden) || v.hidden.length > leaves.length || !v.hidden.every(id => typeof id === 'string' && leaves.includes(id)) || new Set(v.hidden).size !== v.hidden.length) throw new Error('Invalid anatomy visibility.');
hidden = [...v.hidden].sort();
}
const number = (key: string, min: number, max: number) => {
const n = v[key]; if (typeof n !== 'number' || !Number.isFinite(n) || n < min || n > max) throw new Error('Invalid inspection camera.'); return n;
};
return { version: 2, layer, target: v.target as string | null, hidden,
yaw: number('yaw', -Math.PI, Math.PI), pitch: number('pitch', -1.45, 1.45), distance: number('distance', .08, 5.5) };
}
