@ikijs/editor 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/document.ts","../src/mesh-uv.ts","../src/commands.ts","../src/grid-keyform.ts","../src/reparent.ts","../src/alpha-bbox.ts","../src/layer-measure.ts","../src/binding-capture.ts","../src/atlas.ts","../src/factories.ts","../src/auto-rig/profile.ts","../src/auto-rig/types.ts","../src/auto-rig/roles.ts","../src/auto-rig/generate.ts","../src/auto-rig/animations.ts","../src/auto-rig/layout.ts","../src/auto-rig/checks.ts","../src/auto-rig/context.ts","../src/auto-rig/grid.ts","../src/auto-rig/head.ts","../src/auto-rig/fields.ts","../src/auto-rig/face-mesh.ts","../src/auto-rig/solve.ts","../src/auto-rig/drivers.ts"],"sourcesContent":["export {\n EditorDocument,\n type AtlasAssignment,\n type ApplyAtlasInput,\n} from \"./document\";\nexport {\n AddDeformer,\n AddPart,\n AddPhysicsRig,\n CaptureGridKeyform,\n DeleteDeformer,\n DeletePart,\n DeletePhysicsRig,\n SetDeformerBindings,\n SetDeformerParent,\n SetDeformerPivot,\n SetDeformerPivotX,\n SetDeformerPivotY,\n SetDeformerTransform,\n SetPartBindings,\n SetPartColor,\n SetPartDeformer,\n SetPartMesh,\n SetPartHeight,\n SetPartOrder,\n SetPartTransform,\n SetPartWidth,\n SetPhysicsRig,\n type DeformerTransformChannel,\n type EditCommand,\n type EditTransformChannel,\n} from \"./commands\";\nexport {\n ALPHA_BBOX_THRESHOLD,\n detectAlphaBbox,\n type AlphaBbox,\n} from \"./alpha-bbox\";\nexport {\n ALPHA_OPAQUE,\n HEAD_BAND,\n SPECK_CORE_FRACTION,\n createLayerSetMeasurer,\n denseCoreOf,\n foregroundSpan,\n headHalfOf,\n isSpeckCore,\n type LayerSetMeasurement,\n type LayerSetMeasurer,\n type RgbaLayer,\n} from \"./layer-measure\";\nexport { captureBindingEndpoint } from \"./binding-capture\";\nexport {\n computeGridOffsets,\n interpolateGridOffsets,\n upsertGridKeyform,\n} from \"./grid-keyform\";\nexport {\n packAtlas,\n uvRectFor,\n ATLAS_PADDING,\n UV_INSET_PX,\n type AtlasSource,\n type AtlasPlacement,\n type AtlasLayout,\n} from \"./atlas\";\nexport {\n validateDeformerDelete,\n validateDeformerReparent,\n validatePartAttach,\n} from \"./reparent\";\nexport {\n createDefaultPart,\n createDefaultMatrixDeformer,\n createDefaultWarpDeformer,\n createGridMesh,\n} from \"./factories\";\nexport {\n DEFAULT_TURN_TARGETS,\n TurnTargetError,\n generateIkiFromLayerSet,\n parseLayerRoles,\n type IrisStrand,\n type LayerInput,\n type RigStyle,\n type StrandOverlap,\n type TurnDepths,\n type TurnSolveReport,\n type TurnTargets,\n} from \"./auto-rig\";\n","import { parseIkiModel } from \"@ikijs/format\";\nimport type {\n IkiBinding,\n IkiDeformer,\n IkiDeformerBinding,\n IkiDeformerTransform,\n IkiMatrixDeformer,\n IkiModel,\n IkiPart,\n IkiPhysics,\n IkiTexture,\n IkiTransform,\n IkiUvRect,\n IkiWarpDeformer,\n} from \"@ikijs/format\";\n\nimport type { EditCommand } from \"./commands\";\nimport { remapMeshUvsToRect } from \"./mesh-uv\";\n\n/**\n * One part mapped to an imported atlas source. `index` is always 0 because the\n * atlas is a single page; only the `uv` sub-rectangle varies per part.\n */\nexport interface AtlasAssignment {\n partId: string;\n uv: IkiUvRect;\n}\n\n/** Input to {@link EditorDocument.applyAtlas}: the new atlas table plus the\n * per-part UV assignments into it. */\nexport interface ApplyAtlasInput {\n textures: IkiTexture[];\n partTextureAssignments: AtlasAssignment[];\n}\n\n/**\n * In-memory editing session over a single {@link IkiModel}. The model is held\n * directly (no superset) and mutated in place by invertible {@link EditCommand}s\n * pushed through {@link execute}; undo/redo invert/re-apply them.\n *\n * The constructor `structuredClone`s the input so the caller's model is never\n * mutated. Parts are addressed by stable `id`, never by array index.\n */\nexport class EditorDocument {\n private readonly model: IkiModel;\n private readonly undoStack: EditCommand[] = [];\n private readonly redoStack: EditCommand[] = [];\n /** Editor-only session state, never serialized; keyed by stable part id. The\n * unmodified BASE local uvs of every mesh part, captured once at construction\n * so atlas remaps always derive from the original (idempotent). */\n private readonly baseMeshUvs = new Map<string, number[]>();\n\n constructor(model: IkiModel) {\n this.model = structuredClone(model);\n // Capture-once base UVs. Scope: assumes the loaded model's mesh parts carry\n // original LOCAL 0..1 uvs (true for the sample). Restoring base UVs after\n // reloading an already-textured exported model is out of scope (deferred —\n // needs project-file persistence).\n for (const part of this.model.parts) {\n if (part.mesh) {\n this.baseMeshUvs.set(part.id, part.mesh.uvs.slice());\n }\n }\n }\n\n /** Live reference to the working model — for READ access. Mutate it only\n * through {@link execute}/{@link undo}/{@link redo}. */\n getModel(): IkiModel {\n return this.model;\n }\n\n /** Resolve a part by stable id. Throws a plain `Error` (NOT an\n * `IkiFormatError`) with a path-qualified message if the id is unknown. */\n findPart(id: string): IkiPart {\n const part = this.model.parts.find((p) => p.id === id);\n if (!part) {\n throw new Error(`parts: no part with id \"${id}\"`);\n }\n return part;\n }\n\n /** Resolve a warp deformer by stable id. Throws a path-qualified plain\n * `Error` if no deformer matches the id or the match is not a warp deformer.\n * READ/mutate-through accessor, consistent with {@link findPart}. */\n findWarpDeformer(id: string): IkiWarpDeformer {\n const deformer = this.model.deformers?.find((d) => d.id === id);\n if (!deformer || deformer.kind !== \"warp\") {\n throw new Error(`deformers: no warp deformer with id \"${id}\"`);\n }\n return deformer;\n }\n\n /** Resolve a matrix deformer by stable id. Throws a path-qualified plain\n * `Error` if no deformer matches the id or the match is a warp deformer\n * (`kind === \"warp\"`). A `kind` of `\"matrix\"` or `undefined` is a matrix\n * deformer. READ/mutate-through accessor, consistent with {@link findPart}. */\n findMatrixDeformer(id: string): IkiMatrixDeformer {\n const deformer = this.model.deformers?.find((d) => d.id === id);\n if (!deformer || deformer.kind === \"warp\") {\n throw new Error(`deformers: no matrix deformer with id \"${id}\"`);\n }\n return deformer;\n }\n\n /** Resolve any deformer (matrix or warp) by stable id. Throws a\n * path-qualified plain `Error` if no deformer matches the id.\n * READ/mutate-through accessor, consistent with {@link findPart}. */\n findDeformer(id: string): IkiDeformer {\n const deformer = this.model.deformers?.find((d) => d.id === id);\n if (!deformer) {\n throw new Error(`deformers: no deformer with id \"${id}\"`);\n }\n return deformer;\n }\n\n /** Resolve a physics rig by stable id. Throws a path-qualified plain `Error`\n * if no rig matches the id. The `physics` array is optional, so guard it.\n * READ/mutate-through accessor, consistent with {@link findDeformer}. */\n findPhysicsRig(id: string): IkiPhysics {\n const rig = this.model.physics?.find((r) => r.id === id);\n if (!rig) {\n throw new Error(`physics: no physics rig with id \"${id}\"`);\n }\n return rig;\n }\n\n /**\n * Record the base mesh UVs for a part inserted AFTER construction (e.g. by\n * {@link AddPart}). Returns the PRIOR entry for that id (or `undefined` if\n * none existed) so the caller can restore it on undo. No-op for meshless\n * parts (returns `undefined`). Must be called by any command that pushes a\n * mesh part into the model so the part joins the constructor-captured base-UV\n * side state required by {@link applyAtlas}.\n *\n * The returned prior value is what {@link restoreBaseMeshUvs} expects on\n * undo — pass it verbatim. Hazard guarded: DeletePart(X) → AddPart(X′) →\n * undo(add) → undo(delete); without restore, X's constructor-captured entry\n * would be permanently gone after undo of the add, causing applyAtlas to\n * fail when X is restored.\n */\n captureBaseMeshUvs(partId: string): number[] | undefined {\n const prev = this.baseMeshUvs.get(partId);\n const part = this.model.parts.find((p) => p.id === partId);\n if (part?.mesh) {\n this.baseMeshUvs.set(partId, part.mesh.uvs.slice());\n }\n return prev;\n }\n\n /**\n * Restore the base-UV side state to exactly what it was before a\n * {@link captureBaseMeshUvs} call. Called from {@link AddPart.invert}:\n * pass the value returned by captureBaseMeshUvs on first apply.\n * - `prev` is `number[]` → sets the entry (restores a prior mesh's base).\n * - `prev` is `undefined` → deletes the entry (no entry existed before the\n * add, so a later different-mesh part reusing the id must not inherit this\n * one's base).\n * DeletePart does NOT call this — the entry persists across delete/undo so\n * the restored part still has its base available for applyAtlas.\n */\n restoreBaseMeshUvs(partId: string, prev: number[] | undefined): void {\n if (prev !== undefined) {\n this.baseMeshUvs.set(partId, prev);\n } else {\n this.baseMeshUvs.delete(partId);\n }\n }\n\n /** The construction-captured base UVs for a mesh part. Throws a path-qualified\n * plain `Error` if absent. SINGLE accessor for both apply branches — never\n * read `baseMeshUvs` with a bare `!` elsewhere. */\n private requireBaseUvs(partId: string): number[] {\n const base = this.baseMeshUvs.get(partId);\n if (!base) {\n throw new Error(`parts: no base mesh uvs captured for part \"${partId}\"`);\n }\n return base;\n }\n\n /**\n * Replace the atlas table and rewrite every part's texture reference in a\n * single atomic step. For every part in `partTextureAssignments` set\n * `texture = { index: 0, uv }`; CLEAR `texture` (delete the key) on every\n * other part.\n *\n * Mesh parts are textured as a MATCHED PAIR: an assigned mesh part also has\n * its per-vertex `mesh.uvs` remapped (from the construction-captured base)\n * into the same `uv` rect; an unassigned mesh part has its `mesh.uvs` restored\n * to that base. Quad parts carry `texture.uv` only and are untouched here.\n *\n * Deliberately NON-undoable: it does NOT push to or clear the undo/redo\n * stacks (texture/atlas state is not undoable in 5b — the unified\n * editor-state superset is deferred to 5d). `canUndo()`/`canRedo()` are\n * unchanged after a call.\n *\n * Validate-all-then-apply: structural input validation, per-partId\n * resolution, and a base-UV preflight over every mesh part all run BEFORE any\n * mutation, so a bad input (wrong shape, duplicate partId, unknown partId, or\n * a mesh part with no captured base) throws a plain `Error` and leaves the\n * model exactly as it was — never a partial application.\n */\n applyAtlas(input: ApplyAtlasInput): void {\n // Step A — structural validation of the input shape.\n const { texture, assignmentsByPart } = this.normalizeAtlasInput(input);\n\n // Step B — resolve every partId before mutating anything.\n const resolved = new Map<IkiPart, IkiUvRect>();\n for (const [partId, uv] of assignmentsByPart) {\n resolved.set(this.findPart(partId), uv);\n }\n\n // Step C — preflight base UVs for EVERY mesh part (assigned AND unassigned):\n // the mutate loop's clear/restore branch also reads the base of unassigned\n // mesh parts, so this guard must cover them before any write so atomicity\n // (validate-all-then-apply) holds.\n for (const part of this.model.parts) {\n if (part.mesh) {\n this.requireBaseUvs(part.id);\n }\n }\n\n // Mutate — only reached when A + B + C all pass.\n this.model.textures =\n texture === undefined ? undefined : [{ source: texture.source }];\n for (const part of this.model.parts) {\n const uv = resolved.get(part);\n if (uv) {\n part.texture = {\n index: 0,\n uv: { x: uv.x, y: uv.y, width: uv.width, height: uv.height },\n };\n if (part.mesh) {\n // Replace the mesh object so each part owns its own uvs array —\n // de-aliases parts that shared the same mesh object in the input model.\n part.mesh = {\n ...part.mesh,\n uvs: remapMeshUvsToRect(this.requireBaseUvs(part.id), uv),\n };\n }\n } else {\n delete part.texture;\n if (part.mesh) {\n // Same spread here to break aliasing on restore as well.\n part.mesh = {\n ...part.mesh,\n uvs: this.requireBaseUvs(part.id).slice(),\n };\n }\n }\n }\n }\n\n /**\n * Clear a model-committed texture reference from a single part. Deliberately\n * NON-undoable, matching {@link applyAtlas} — texture/atlas state is not in\n * the undo model (unified editor-state is deferred). Does NOT push to or\n * clear the undo/redo stacks. Does NOT touch `mesh.uvs` — atlas-space UVs on\n * an untextured mesh are inert for color rendering; a later atlas import\n * remaps from the base UVs anyway.\n *\n * This is the single consistent texture/atlas undo boundary: by the time a\n * part is deletable (no texture), its DeletePart snapshot carries no texture\n * reference, so no stale index can resurface on undo after a later atlas\n * repack.\n *\n * Throws a path-qualified plain `Error` (NOT `IkiFormatError`) if the part\n * id is unknown — same contract as {@link findPart}.\n */\n clearPartTextureRef(partId: string): void {\n const part = this.findPart(partId);\n delete part.texture;\n }\n\n /**\n * Validate the structural shape of an {@link ApplyAtlasInput} without\n * touching the model, returning a known-good `{ texture?, assignmentsByPart }`\n * for {@link applyAtlas} to resolve and apply.\n */\n private normalizeAtlasInput(input: ApplyAtlasInput): {\n texture?: IkiTexture;\n assignmentsByPart: Map<string, IkiUvRect>;\n } {\n if (input.textures.length > 1) {\n throw new Error(\n `applyAtlas: textures must be a single atlas page (got ${input.textures.length})`,\n );\n }\n if (\n input.partTextureAssignments.length > 0 &&\n input.textures.length !== 1\n ) {\n throw new Error(\n \"applyAtlas: partTextureAssignments require exactly one texture\",\n );\n }\n\n const assignmentsByPart = new Map<string, IkiUvRect>();\n for (const { partId, uv } of input.partTextureAssignments) {\n if (assignmentsByPart.has(partId)) {\n throw new Error(\n `applyAtlas: duplicate partId \"${partId}\" in partTextureAssignments`,\n );\n }\n assignmentsByPart.set(partId, uv);\n }\n\n return { texture: input.textures[0], assignmentsByPart };\n }\n\n /**\n * Overwrite a part's whole transform with a fresh copy of `transform`.\n * Replacing the whole object (rather than individual channels) preserves any\n * optional keys already absent from the incoming value.\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * pose. Does NOT push to or clear undoStack/redoStack (sibling to\n * {@link applyAtlas}'s non-undoable boundary). The caller is responsible for\n * restoring the exact prior snapshot when the capture pose ends.\n *\n * `IkiTransform` is a flat number map, so a shallow spread is a sufficient\n * deep copy — no aliasing of the caller's object remains.\n */\n setPartTransformEphemeral(partId: string, transform: IkiTransform): void {\n const part = this.findPart(partId);\n part.transform = { ...transform };\n }\n\n /**\n * Overwrite a matrix deformer's optional transform with a fresh copy, or\n * delete it when `transform` is `undefined`.\n * `undefined` deletes the key, restoring the deformer to the same state as\n * one that never had a transform (absent-vs-present matters for downstream\n * renderers).\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * pose. Does NOT push to or clear undoStack/redoStack (sibling to\n * {@link applyAtlas}'s non-undoable boundary). The caller is responsible for\n * restoring the exact prior snapshot when the capture pose ends.\n *\n * `IkiDeformerTransform` is a flat number map, so a shallow spread is a\n * sufficient deep copy — no aliasing of the caller's object remains.\n */\n setDeformerTransformEphemeral(\n deformerId: string,\n transform: IkiDeformerTransform | undefined,\n ): void {\n const deformer = this.findMatrixDeformer(deformerId);\n if (transform === undefined) {\n delete deformer.transform;\n } else {\n deformer.transform = { ...transform };\n }\n }\n\n /**\n * Overwrite a part's whole bindings array with a fresh deep copy, or delete\n * the key when `bindings` is empty.\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * neutralization (zeroing the row being recaptured so the preview reflects\n * base-only during posing). Does NOT push to or clear undoStack/redoStack.\n * The caller is responsible for restoring the original bindings when the\n * capture session ends.\n */\n setPartBindingsEphemeral(partId: string, bindings: IkiBinding[]): void {\n const part = this.findPart(partId);\n if (bindings.length > 0) {\n part.bindings = bindings.map((b) => ({ ...b }));\n } else {\n delete part.bindings;\n }\n }\n\n /**\n * Overwrite a matrix deformer's whole bindings array with a fresh deep copy,\n * or delete the key when `bindings` is empty.\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * neutralization (zeroing the row being recaptured so the preview reflects\n * base-only during posing). Does NOT push to or clear undoStack/redoStack.\n * The caller is responsible for restoring the original bindings when the\n * capture session ends.\n */\n setDeformerBindingsEphemeral(\n deformerId: string,\n bindings: IkiDeformerBinding[],\n ): void {\n const deformer = this.findMatrixDeformer(deformerId);\n if (bindings.length > 0) {\n deformer.bindings = bindings.map((b) => ({ ...b }));\n } else {\n delete deformer.bindings;\n }\n }\n\n /** Apply a command and record it as one undo step. Clears the redo stack. */\n execute(cmd: EditCommand): void {\n cmd.apply(this);\n this.undoStack.push(cmd);\n this.redoStack.length = 0;\n }\n\n /** Invert the most recent command and move it onto the redo stack. */\n undo(): void {\n const cmd = this.undoStack.pop();\n if (!cmd) return;\n cmd.invert(this);\n this.redoStack.push(cmd);\n }\n\n /** Re-apply the most recently undone command and move it back onto undo. */\n redo(): void {\n const cmd = this.redoStack.pop();\n if (!cmd) return;\n cmd.apply(this);\n this.undoStack.push(cmd);\n }\n\n canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n /**\n * Validate and export the current working model by running it through\n * {@link parseIkiModel}. Uses `structuredClone` so the validator's\n * normalized output cannot alias the working model. Propagates\n * `IkiFormatError` unchanged on failure — callers surface `.message`.\n */\n toIkiModel(): IkiModel {\n return parseIkiModel(structuredClone(this.model));\n }\n\n /**\n * Pretty-print the validated model as a `.iki` JSON string. Always\n * validates first — invalid documents never reach a file.\n */\n serialize(): string {\n return JSON.stringify(this.toIkiModel(), null, 2);\n }\n}\n","import type { IkiUvRect } from \"@ikijs/format\";\n\n/**\n * Affinely map a mesh's BASE local UVs into an atlas sub-rectangle.\n *\n * Per the `@ikijs/format` UV convention (top-left origin, +y down, 0..1; see\n * {@link IkiUvRect}/{@link IkiMesh}), the input is the part's BASE local uvs and\n * the output places each component into `rect` with NO flip — base UV space and\n * `rect` share the same orientation:\n * out[2i] = rect.x + baseUvs[2i] * rect.width\n * out[2i+1] = rect.y + baseUvs[2i+1] * rect.height\n *\n * The caller guarantees `rect` is inset/clamped (via `uvRectFor`) so every\n * output component stays within 0..1 and passes the format validator.\n *\n * Returns a fresh array; `baseUvs` is never mutated.\n */\nexport function remapMeshUvsToRect(\n baseUvs: number[],\n rect: IkiUvRect,\n): number[] {\n if (baseUvs.length % 2 !== 0) {\n throw new Error(\n `remapMeshUvsToRect: baseUvs must have an even length (u,v pairs), got ${baseUvs.length}`,\n );\n }\n\n const out = new Array<number>(baseUvs.length);\n for (let i = 0; i < baseUvs.length; i += 2) {\n out[i] = rect.x + baseUvs[i] * rect.width;\n out[i + 1] = rect.y + baseUvs[i + 1] * rect.height;\n }\n return out;\n}\n","import type {\n IkiBinding,\n IkiDeformer,\n IkiDeformerBinding,\n IkiDeformerTransform,\n IkiGridKeyform,\n IkiMatrixDeformer,\n IkiMesh,\n IkiModel,\n IkiPart,\n IkiPhysics,\n} from \"@ikijs/format\";\nimport {\n IKI_FORMAT_VERSION,\n IkiFormatError,\n parseIkiModel,\n} from \"@ikijs/format\";\n\nimport type { EditorDocument } from \"./document\";\nimport { upsertGridKeyform } from \"./grid-keyform\";\nimport { remapMeshUvsToRect } from \"./mesh-uv\";\nimport {\n validateDeformerDelete,\n validateDeformerReparent,\n validatePartAttach,\n} from \"./reparent\";\n\n/**\n * Scan the id-flat namespace (parts first, then deformers) and return which\n * array already holds `id`, or `undefined` if the id is free. Parts and\n * deformers share a single flat id namespace, so both arrays must be checked\n * to produce a source-qualified collision message.\n */\nfunction findIdCollision(\n model: IkiModel,\n id: string,\n): \"part\" | \"deformer\" | undefined {\n for (const p of model.parts) {\n if (p.id === id) return \"part\";\n }\n for (const d of model.deformers ?? []) {\n if (d.id === id) return \"deformer\";\n }\n return undefined;\n}\n\n/**\n * One invertible edit. The document is passed IN at apply/invert time — a\n * command is constructed from `(partId, value)` alone, before any document\n * exists — so the same command object can be applied, inverted, and re-applied\n * by the undo/redo stack.\n *\n * Prior-value capture happens exactly ONCE, on the first {@link apply}. `redo`\n * (a second `apply`) reuses that captured value rather than re-reading the\n * current field, so undo always restores the original target.\n */\nexport interface EditCommand {\n apply(doc: EditorDocument): void;\n invert(doc: EditorDocument): void;\n readonly label: string;\n}\n\n/** Channels of {@link IkiTransform} this editor can edit (object-field names,\n * NOT the binding `IkiTransformChannel` vocabulary). */\nexport type EditTransformChannel =\n | \"x\"\n | \"y\"\n | \"rotation\"\n | \"scaleX\"\n | \"scaleY\"\n | \"opacity\";\n\n/**\n * Generic single-field command: reads/writes one field of the resolved part via\n * a getter/setter closure, capturing the prior value on the first `apply` and\n * restoring it on `invert`. `T` is the captured value's type; for cloned values\n * (the color tuple) the getter/setter perform the copy.\n */\nclass FieldCommand<T> implements EditCommand {\n readonly label: string;\n private captured = false;\n private prevValue!: T;\n\n constructor(\n private readonly partId: string,\n private readonly newValue: T,\n label: string,\n private readonly get: (part: IkiPart) => T,\n private readonly set: (part: IkiPart, value: T) => void,\n ) {\n this.label = label;\n }\n\n apply(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n if (!this.captured) {\n this.prevValue = this.get(part);\n this.captured = true;\n }\n this.set(part, this.newValue);\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n this.set(part, this.prevValue);\n }\n}\n\n/** Edit a part's RGBA fill. The 4-tuple is mutable, so the command clones on\n * construction (caller's array), on capture (part's current color), and on\n * assign (writing to the part) — it never retains the caller's or model's\n * array by reference. */\nexport class SetPartColor extends FieldCommand<\n [number, number, number, number]\n> {\n constructor(partId: string, rgba: [number, number, number, number]) {\n super(\n partId,\n [...rgba] as [number, number, number, number],\n \"Set color\",\n (part) => [...part.color],\n (part, value) => {\n part.color = [...value] as [number, number, number, number];\n },\n );\n }\n}\n\n/** Edit a part's width (model-space units). */\nexport class SetPartWidth extends FieldCommand<number> {\n constructor(partId: string, value: number) {\n super(\n partId,\n value,\n \"Set width\",\n (part) => part.width,\n (part, v) => {\n part.width = v;\n },\n );\n }\n}\n\n/** Edit a part's height (model-space units). */\nexport class SetPartHeight extends FieldCommand<number> {\n constructor(partId: string, value: number) {\n super(\n partId,\n value,\n \"Set height\",\n (part) => part.height,\n (part, v) => {\n part.height = v;\n },\n );\n }\n}\n\n/** Edit a part's paint order. */\nexport class SetPartOrder extends FieldCommand<number> {\n constructor(partId: string, value: number) {\n super(\n partId,\n value,\n \"Set order\",\n (part) => part.order,\n (part, v) => {\n part.order = v;\n },\n );\n }\n}\n\n/**\n * Edit one channel of a part's base transform. `x`/`y` are required; the rest\n * are optional and may be absent on the part. For an optional channel the\n * command captures the raw current value INCLUDING `undefined`, and restoring\n * `undefined` DELETES the key so undo returns the part to its original\n * (possibly-omitted) shape. Engine defaults (rotation 0 / scale 1 / opacity 1)\n * are NOT substituted here.\n */\nexport class SetPartTransform extends FieldCommand<number | undefined> {\n constructor(partId: string, channel: EditTransformChannel, value: number) {\n super(\n partId,\n value,\n \"Set transform\",\n (part) => part.transform[channel],\n (part, v) => {\n if (v === undefined) {\n delete part.transform[channel];\n } else {\n part.transform[channel] = v;\n }\n },\n );\n }\n}\n\n/**\n * Capture the warp deformer's grid as one keyform at the driving parameter\n * `value`, upserting `offsets` into the deformer's single grid warp. The 4-tuple-style\n * mutable `offsets` array is cloned on construction so a later caller mutation\n * cannot corrupt apply/redo (mirrors {@link SetPartColor}).\n *\n * `apply` validates BEFORE mutating: the deformer must have exactly one grid\n * warp (several are refused — which driver to write into is ambiguous), the\n * offsets length must equal `grid.points.length`, and `value` must lie within\n * the driving parameter's declared `[min,max]` (fail fast, before\n * `parseIkiModel` would reject it). Prior keyforms are deep-copied once on the\n * first `apply` (capture-once like {@link FieldCommand}); `invert` restores\n * that deep copy so re-apply after undo never aliases.\n */\nexport class CaptureGridKeyform implements EditCommand {\n readonly label = \"Capture grid keyform\";\n private readonly offsets: number[];\n private captured = false;\n private prevKeyforms!: IkiGridKeyform[];\n\n constructor(\n private readonly deformerId: string,\n private readonly value: number,\n offsets: number[],\n ) {\n this.offsets = [...offsets];\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findWarpDeformer(this.deformerId);\n const count = deformer.warps?.length ?? 0;\n if (count > 1) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps: ${count} grid warps — capture targets a deformer with exactly one grid warp (which entry to write into is ambiguous)`,\n );\n }\n const warp = deformer.warps?.[0];\n if (!warp) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps: no grid warp to capture into`,\n );\n }\n if (this.offsets.length !== deformer.grid.points.length) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps[0].keyforms.offsets length ${this.offsets.length} must equal grid.points length ${deformer.grid.points.length}`,\n );\n }\n const param = doc\n .getModel()\n .parameters.find((p) => p.id === warp.parameter);\n if (!param) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps[0].parameter \"${warp.parameter}\" is not a declared parameter`,\n );\n }\n if (this.value < param.min || this.value > param.max) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps[0].keyforms.value ${this.value} is outside parameter \"${warp.parameter}\" range [${param.min},${param.max}]`,\n );\n }\n\n if (!this.captured) {\n this.prevKeyforms = structuredClone(warp.keyforms);\n this.captured = true;\n }\n warp.keyforms = upsertGridKeyform(warp.keyforms, this.value, [\n ...this.offsets,\n ]);\n }\n\n invert(doc: EditorDocument): void {\n const warp = doc.findWarpDeformer(this.deformerId).warps?.[0];\n if (!warp) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps: no grid warp to restore into`,\n );\n }\n warp.keyforms = structuredClone(this.prevKeyforms);\n }\n}\n\n/**\n * Generic single-field command targeting a matrix deformer, mirroring\n * {@link FieldCommand} but resolving via `doc.findMatrixDeformer` instead of\n * `doc.findPart`. Capture-once on first `apply`; restore on `invert`.\n */\nclass DeformerFieldCommand<T> implements EditCommand {\n readonly label: string;\n private captured = false;\n private prevValue!: T;\n\n constructor(\n private readonly deformerId: string,\n private readonly newValue: T,\n label: string,\n private readonly get: (deformer: IkiMatrixDeformer) => T,\n private readonly set: (deformer: IkiMatrixDeformer, value: T) => void,\n ) {\n this.label = label;\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (!this.captured) {\n this.prevValue = this.get(deformer);\n this.captured = true;\n }\n this.set(deformer, this.newValue);\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n this.set(deformer, this.prevValue);\n }\n}\n\n/** Edit a matrix deformer's pivot x. */\nexport class SetDeformerPivotX extends DeformerFieldCommand<number> {\n constructor(deformerId: string, value: number) {\n super(\n deformerId,\n value,\n \"Set pivot x\",\n (d) => d.pivot.x,\n (d, v) => {\n d.pivot.x = v;\n },\n );\n }\n}\n\n/** Edit a matrix deformer's pivot y. */\nexport class SetDeformerPivotY extends DeformerFieldCommand<number> {\n constructor(deformerId: string, value: number) {\n super(\n deformerId,\n value,\n \"Set pivot y\",\n (d) => d.pivot.y,\n (d, v) => {\n d.pivot.y = v;\n },\n );\n }\n}\n\n/**\n * Set a matrix deformer's pivot x and y atomically (one drag = one undo step).\n * {@link SetDeformerPivotX} and {@link SetDeformerPivotY} remain for the\n * Inspector's single-axis number inputs.\n */\nexport class SetDeformerPivot implements EditCommand {\n readonly label = \"Set pivot\";\n private captured = false;\n private prevPivot!: { x: number; y: number };\n private readonly pivot: { x: number; y: number };\n\n constructor(\n private readonly deformerId: string,\n pivot: { x: number; y: number },\n ) {\n // Fresh clone so a caller mutating their arg after construction cannot\n // corrupt apply/redo.\n this.pivot = { x: pivot.x, y: pivot.y };\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (!this.captured) {\n this.prevPivot = { x: deformer.pivot.x, y: deformer.pivot.y };\n this.captured = true;\n }\n deformer.pivot = { x: this.pivot.x, y: this.pivot.y };\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n // Fresh clone — never alias the captured object so repeated undo/redo\n // cycles cannot corrupt the saved prior value.\n deformer.pivot = { x: this.prevPivot.x, y: this.prevPivot.y };\n }\n}\n\n/** Channels of {@link IkiDeformerTransform} this editor can edit. */\nexport type DeformerTransformChannel =\n | \"x\"\n | \"y\"\n | \"rotation\"\n | \"scaleX\"\n | \"scaleY\";\n\n/**\n * Edit one channel of a matrix deformer's base transform. Because\n * {@link IkiDeformerTransform} REQUIRES finite `x` and `y`, this command\n * captures and restores the WHOLE prior `transform` object (present or absent)\n * rather than a single channel, so undo can delete the transform when it did\n * not previously exist, and redo never produces a partial object missing `x`/`y`.\n *\n * When no `transform` is present on the deformer, `apply` creates one from\n * the identity base `{ x: 0, y: 0 }` — the minimal valid shape the validator\n * accepts — then writes the edited channel. For example, editing `rotation`\n * on a transform-less deformer yields `{ x: 0, y: 0, rotation: <value> }`.\n */\nexport class SetDeformerTransform implements EditCommand {\n readonly label = \"Set deformer transform\";\n private captured = false;\n private prevTransform!: IkiDeformerTransform | undefined;\n\n constructor(\n private readonly deformerId: string,\n private readonly channel: DeformerTransformChannel,\n private readonly value: number,\n ) {}\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (!this.captured) {\n // Shallow clone is sufficient — IkiDeformerTransform is a flat number map.\n this.prevTransform =\n deformer.transform === undefined\n ? undefined\n : { ...deformer.transform };\n this.captured = true;\n }\n // Start from the existing transform or the identity base. The identity base\n // is { x: 0, y: 0 } because the validator unconditionally requires finite\n // x and y whenever a transform object is present.\n const next: IkiDeformerTransform = {\n ...(deformer.transform ?? { x: 0, y: 0 }),\n };\n next[this.channel] = this.value;\n deformer.transform = next;\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (this.prevTransform === undefined) {\n delete deformer.transform;\n } else {\n // Assign a fresh clone — never alias the captured object so repeated\n // undo/redo cycles cannot corrupt the saved prior value.\n deformer.transform = { ...this.prevTransform };\n }\n }\n}\n\n/**\n * Replace a matrix deformer's `bindings` array wholesale. A single command\n * covers add, edit, and remove (pass the desired final array; pass `[]` to\n * remove all). Mirrors {@link CaptureGridKeyform}'s deep-copy discipline:\n * clone-on-construction, capture-once, fresh deep copy on invert.\n *\n * Each {@link IkiDeformerBinding} is a flat object so a per-element spread\n * `{ ...b }` is a sufficient deep copy.\n */\nexport class SetDeformerBindings implements EditCommand {\n readonly label = \"Set deformer bindings\";\n private readonly bindings: IkiDeformerBinding[];\n private captured = false;\n private prevBindings!: IkiDeformerBinding[] | undefined;\n\n constructor(\n private readonly deformerId: string,\n bindings: IkiDeformerBinding[],\n ) {\n // Clone the caller's array on construction — prevents post-execute mutation\n // of the caller's array from corrupting apply/redo.\n this.bindings = bindings.map((b) => ({ ...b }));\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n\n // Validate a NARROW synthetic candidate before capture/mutate, exactly as\n // {@link SetPartBindings} does and for the same reason: a full\n // structuredClone(doc.getModel()) would also validate parts and deformers\n // the user is not editing, and those routinely hold in-flight `NaN` from an\n // emptied numeric input — so an unrelated blank field would refuse this\n // edit, and report it against the wrong object. The Inspector offers every\n // parameter in the model, so an undeclared id, a non-finite endpoint, or a\n // non-matrix channel must still be caught here.\n //\n // NOT covered by this shape: a binding that feeds a physics chain's own\n // anchor. That rule needs the whole deformer hierarchy, and reproducing it\n // over a sanitized model would mean hand-maintaining a second model shape\n // beside the validator. It stays an export-time check in `toIkiModel()`.\n // Parts and deformers share one flat id namespace, so the two synthetic\n // objects below must not both be \"_\".\n const candidateDeformer: Record<string, unknown> = {\n kind: \"matrix\",\n id: \"_d\",\n pivot: { x: 0, y: 0 },\n };\n if (this.bindings.length > 0) {\n candidateDeformer.bindings = this.bindings.map((b) => ({ ...b }));\n }\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [\n {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n },\n ],\n deformers: [candidateDeformer],\n };\n // The synthetic deformer is always at deformers[0]; rewrite that prefix so\n // the surfaced error names the real target.\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n throw new IkiFormatError(\n e.message.replace(\n /^deformers\\[0\\]/,\n `deformers.\"${this.deformerId}\"`,\n ),\n );\n }\n throw e;\n }\n\n if (!this.captured) {\n // Preserve the original absent-vs-empty distinction.\n this.prevBindings =\n deformer.bindings === undefined\n ? undefined\n : deformer.bindings.map((b) => ({ ...b }));\n this.captured = true;\n }\n if (this.bindings.length > 0) {\n // Assign a fresh deep copy — model must never alias the command's stored array.\n deformer.bindings = this.bindings.map((b) => ({ ...b }));\n } else {\n // Delete the key on empty: keeps the model shape minimal and correctly\n // represents \"no bindings\" as an absent key rather than an empty array.\n delete deformer.bindings;\n }\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (this.prevBindings === undefined) {\n delete deformer.bindings;\n } else {\n // Assign a fresh deep copy — never alias the captured array so re-apply\n // after undo cannot corrupt the saved prior value.\n deformer.bindings = this.prevBindings.map((b) => ({ ...b }));\n }\n }\n}\n\n/**\n * Reparent a deformer (matrix or warp) under a new parent, or promote it to\n * root (`newParentId === undefined`). Calls {@link validateDeformerReparent}\n * FIRST so invalid reparents (cycles, warp-under-warp, a pivot outside the new\n * warp parent's grid, unknown id) throw before any\n * capture or mutation — a throwing apply leaves the model and undo stack\n * untouched.\n *\n * Absent-vs-present distinction: captures both the prior `parent` value AND\n * whether the key was present on the object, so `invert` can delete the key\n * (restore \"absent\") rather than blindly assigning `undefined`.\n */\nexport class SetDeformerParent implements EditCommand {\n readonly label = \"Set deformer parent\";\n private captured = false;\n private prevParent: string | undefined = undefined;\n private prevHadParent = false;\n\n constructor(\n private readonly deformerId: string,\n private readonly newParentId: string | undefined,\n ) {}\n\n apply(doc: EditorDocument): void {\n // Validate FIRST — throws before capture/mutate on any violation.\n validateDeformerReparent(\n doc.getModel().deformers ?? [],\n this.deformerId,\n this.newParentId,\n );\n\n // A new ANCESTOR can still bind a parameter that a physics chain anchored\n // here emits, which the format rejects as feedback. That rule needs the\n // whole hierarchy, and validating a full clone of the document here refuses\n // the edit whenever any unrelated part or deformer holds in-flight `NaN`\n // from an emptied numeric input — reporting it against the wrong object.\n // So the feedback case stays an export-time check in `toIkiModel()`, where\n // it was before, rather than trading a rare corruption for a common block.\n //\n // Known cost of that trade: the host surfaces the export error (the editor\n // app re-exports on a ~200ms debounce), but the message names the CHAIN, not\n // the edit — reparent `headDeformer` and you get\n // `physicsChains[0].segments[1].output.parameter \"...\" feeds its own anchor\n // deformer chain (feedback)`, which reads as a complaint about a hair lock.\n // If a friendlier error surface ever lands, this is the message to special-case.\n const deformer = doc.findDeformer(this.deformerId);\n if (!this.captured) {\n this.prevHadParent = Object.prototype.hasOwnProperty.call(\n deformer,\n \"parent\",\n );\n this.prevParent = deformer.parent;\n this.captured = true;\n }\n if (this.newParentId !== undefined) {\n deformer.parent = this.newParentId;\n } else {\n delete deformer.parent;\n }\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findDeformer(this.deformerId);\n if (this.prevHadParent) {\n deformer.parent = this.prevParent;\n } else {\n delete deformer.parent;\n }\n }\n}\n\n/**\n * Add a new part to the model. Validates the candidate model with\n * {@link parseIkiModel} BEFORE mutating, so a structurally invalid part\n * (bad color tuple, missing required fields, id collision with a deformer)\n * throws an `IkiFormatError` and leaves the model untouched.\n *\n * Captures the prior base-UV entry for the part's id on the FIRST apply so\n * invert can restore the exact pre-add state. This guards the id-reuse hazard:\n * DeletePart(X) → AddPart(X′, different mesh) → undo(add) → undo(delete) —\n * without restore, X's constructor-captured base would be gone, causing\n * applyAtlas to fail when X is restored by the undo of the delete.\n */\nexport class AddPart implements EditCommand {\n readonly label = \"Add part\";\n private readonly part: IkiPart;\n private captured = false;\n private prevBaseMeshUvs: number[] | undefined = undefined;\n\n constructor(part: IkiPart) {\n // Clone on construction — prevents caller mutation from corrupting apply/redo.\n this.part = structuredClone(part);\n }\n\n apply(doc: EditorDocument): void {\n // (a) Cheap id-uniqueness pre-check with a source-qualified message.\n const hit = findIdCollision(doc.getModel(), this.part.id);\n if (hit === \"part\") {\n throw new Error(\n `parts: id \"${this.part.id}\" collides with an existing part id`,\n );\n }\n if (hit === \"deformer\") {\n throw new Error(\n `parts: id \"${this.part.id}\" collides with an existing deformer id`,\n );\n }\n\n // (b) Full structural validation on a candidate clone — propagate\n // IkiFormatError unchanged so the caller gets a path-qualified message.\n const candidate = structuredClone(doc.getModel());\n candidate.parts.push(structuredClone(this.part));\n parseIkiModel(candidate);\n\n // (c) All checks pass — mutate the real model with a fresh clone so the\n // model never aliases the command's stored part.\n doc.getModel().parts.push(structuredClone(this.part));\n\n // Register base mesh UVs so applyAtlas can remap this part. Capture the\n // prior entry on the FIRST apply only — redo must NOT re-capture or it\n // would clobber the saved prior and make invert unable to restore correctly.\n const prev = doc.captureBaseMeshUvs(this.part.id);\n if (!this.captured) {\n this.prevBaseMeshUvs = prev;\n this.captured = true;\n }\n }\n\n invert(doc: EditorDocument): void {\n const parts = doc.getModel().parts;\n const i = parts.findIndex((p) => p.id === this.part.id);\n if (i !== -1) parts.splice(i, 1);\n // Restore the exact prior base-UV state so a constructor-captured entry for\n // a deleted part with this id survives the undo of the add.\n doc.restoreBaseMeshUvs(this.part.id, this.prevBaseMeshUvs);\n }\n}\n\n/**\n * Add a new deformer (matrix or warp) to the model. Validates the candidate\n * model with {@link parseIkiModel} BEFORE mutating — this enforces the warp\n * rest-grid invariant, points length, pivot, parent, and bindings without\n * hand-rolling partial checks. Mirrors {@link AddPart} but also tracks whether\n * `model.deformers` was absent before the first apply, so `invert` can restore\n * the exact key-absence state (mirrors {@link SetDeformerBindings}).\n */\nexport class AddDeformer implements EditCommand {\n readonly label = \"Add deformer\";\n private readonly deformer: IkiDeformer;\n private captured = false;\n private prevDeformersAbsent = false;\n\n constructor(deformer: IkiDeformer) {\n // Clone on construction — prevents caller mutation from corrupting apply/redo.\n this.deformer = structuredClone(deformer);\n }\n\n apply(doc: EditorDocument): void {\n const model = doc.getModel();\n\n // (a) Cheap id-uniqueness pre-check with a source-qualified message.\n const hit = findIdCollision(model, this.deformer.id);\n if (hit === \"deformer\") {\n throw new Error(\n `deformers: id \"${this.deformer.id}\" collides with an existing deformer id`,\n );\n }\n if (hit === \"part\") {\n throw new Error(\n `deformers: id \"${this.deformer.id}\" collides with an existing part id`,\n );\n }\n\n // (b) Full structural validation on a candidate clone.\n const candidate = structuredClone(model);\n candidate.deformers = [\n ...(candidate.deformers ?? []),\n structuredClone(this.deformer),\n ];\n parseIkiModel(candidate);\n\n // (c) All checks pass — capture-once, then mutate.\n if (!this.captured) {\n this.prevDeformersAbsent = model.deformers === undefined;\n this.captured = true;\n }\n if (model.deformers === undefined) {\n model.deformers = [];\n }\n model.deformers.push(structuredClone(this.deformer));\n }\n\n invert(doc: EditorDocument): void {\n const model = doc.getModel();\n const arr = model.deformers;\n if (!arr) return;\n const i = arr.findIndex((d) => d.id === this.deformer.id);\n if (i !== -1) arr.splice(i, 1);\n // Restore the absent-vs-present distinction. If deformers did not exist\n // before apply, delete the key once the array is empty again.\n if (this.prevDeformersAbsent && arr.length === 0) {\n delete model.deformers;\n }\n }\n}\n\n/**\n * Delete a part by id, preserving its original array slot so `invert` restores\n * it at the same position. Slot position is cosmetic (the renderer uses the\n * `order` field for paint ordering), but restoring the index keeps undo\n * visually predictable.\n *\n * No `parseIkiModel` pre-check is needed: removing an element from an already-\n * valid model cannot introduce a structural violation — EXCEPT for clip-mask\n * references, the one part→part reference in the contract. `apply` refuses to\n * delete a part still used as another part's `clip.masks` entry (guard below),\n * so it can never leave a dangling mask ref that would fail `toIkiModel()`.\n *\n * Texture-reference safety (package invariant): `apply` refuses to delete a\n * part that still carries `part.texture`. Texture/atlas state is non-undoable\n * per the 5b boundary; clear the texture first via\n * {@link EditorDocument.clearPartTextureRef} (model-committed) or\n * {@link EditorDocument.applyAtlas} with no assignment (imported) — both are\n * non-undoable. By the time a part is deletable it carries no texture, so\n * `invert` can never restore a stale texture index that would render the wrong\n * atlas region after a later atlas repack. No transactional atlas capture is\n * needed in this command.\n */\nexport class DeletePart implements EditCommand {\n readonly label = \"Delete part\";\n private captured = false;\n private removed!: IkiPart;\n private index!: number;\n\n constructor(private readonly partId: string) {}\n\n apply(doc: EditorDocument): void {\n // Validate FIRST — throws with path-qualified message if unknown.\n const part = doc.findPart(this.partId);\n\n // Texture guard — enforced at the `@ikijs/editor` boundary so public callers\n // cannot bypass it (the example store adds a friendly pre-check, but this\n // is the real invariant). Throw before any capture or mutation.\n if (part.texture !== undefined) {\n throw new Error(\n `parts.\"${this.partId}\": cannot delete — part has a texture reference; clear its texture first`,\n );\n }\n\n const parts = doc.getModel().parts;\n\n // Clip-mask guard — `clip.masks` is the one part→part reference in the model\n // contract. Deleting a referenced mask would leave a dangling ref that fails\n // parseIkiModel on toIkiModel(). Refuse rather than corrupt (mirrors the\n // texture guard above). Throw before any capture or mutation.\n const masker = parts.find(\n (p) => p.id !== this.partId && p.clip?.masks.includes(this.partId),\n );\n if (masker) {\n throw new Error(\n `parts.\"${this.partId}\": cannot delete — used as a clip mask by part \"${masker.id}\"; remove its clip first`,\n );\n }\n\n const i = parts.indexOf(part);\n if (!this.captured) {\n this.removed = structuredClone(part);\n this.index = i;\n this.captured = true;\n }\n parts.splice(i, 1);\n }\n\n invert(doc: EditorDocument): void {\n // Restore at the original slot — exact deep restore including bindings and\n // mesh. No texture key is present (apply enforced that invariant before\n // capture), so the snapshot is always atlas-safe on restore.\n doc.getModel().parts.splice(this.index, 0, structuredClone(this.removed));\n }\n}\n\n/**\n * Delete a deformer by id. Calls {@link validateDeformerDelete} FIRST so the\n * delete is refused while anything still references it — a child deformer, an\n * attached part, or a physics chain anchored to it — enforcing the same\n * referential safety as {@link SetDeformerParent} and {@link SetPartDeformer}.\n *\n * `invert` re-inserts the deformer at its original index.\n */\nexport class DeleteDeformer implements EditCommand {\n readonly label = \"Delete deformer\";\n private captured = false;\n private removed!: IkiDeformer;\n private index!: number;\n\n constructor(private readonly deformerId: string) {}\n\n apply(doc: EditorDocument): void {\n const model = doc.getModel();\n // Validate FIRST — throws before capture/mutate on any referential violation.\n validateDeformerDelete(\n model.deformers ?? [],\n model.parts,\n model.physicsChains ?? [],\n this.deformerId,\n );\n // validateDeformerDelete guarantees the deformer (and thus the array) exists.\n const arr = model.deformers!;\n const i = arr.findIndex((d) => d.id === this.deformerId);\n if (!this.captured) {\n this.removed = structuredClone(arr[i]);\n this.index = i;\n this.captured = true;\n }\n arr.splice(i, 1);\n }\n\n invert(doc: EditorDocument): void {\n // Re-insert at the original slot. `apply` only captures after\n // validateDeformerDelete passed, so the array it spliced out of is present:\n // fabricating one here would hide a broken undo stack and silently restore\n // just this node instead of surfacing the loss of the rest of the hierarchy.\n doc\n .getModel()\n .deformers!.splice(this.index, 0, structuredClone(this.removed));\n }\n}\n\n/**\n * Replace a part's `bindings` array wholesale. A single command covers add,\n * edit, and remove (pass the desired final array; pass `[]` to remove all).\n * Mirrors {@link SetDeformerBindings}'s deep-copy and absent-vs-empty discipline:\n * clone-on-construction, capture-once, fresh deep copy on every assign/invert.\n *\n * Each {@link IkiBinding} is a flat object, so a per-element spread `{ ...b }`\n * is a sufficient deep copy.\n *\n * Validates the WRITTEN bindings against the declared parameters via a narrow\n * synthetic {@link parseIkiModel} candidate (so unrelated in-flight invalid\n * editor state — e.g. a NaN width on another part — cannot false-reject a\n * binding edit). Validation runs BEFORE any mutation; on failure the model and\n * undo stack are left untouched.\n *\n * Empty bindings → omit the `bindings` key on the candidate AND delete\n * `part.bindings` on apply (keeps the model shape minimal; represents \"no\n * bindings\" as an absent key rather than an empty array).\n */\nexport class SetPartBindings implements EditCommand {\n readonly label = \"Set part bindings\";\n private readonly bindings: IkiBinding[];\n private captured = false;\n private prevBindings!: IkiBinding[] | undefined;\n\n constructor(\n private readonly partId: string,\n bindings: IkiBinding[],\n ) {\n // Clone the caller's array on construction — prevents post-execute mutation\n // of the caller's array from corrupting apply/redo.\n this.bindings = bindings.map((b) => ({ ...b }));\n }\n\n apply(doc: EditorDocument): void {\n // Build a narrow synthetic candidate carrying only the validation-relevant\n // context. A full structuredClone(doc.getModel()) is deliberately avoided\n // because unrelated parts may carry NaN in-flight values (e.g. from\n // NumberField.valueAsNumber), which would cause false-positive validation\n // failures. The synthetic model is the minimal shape parseIkiModel accepts.\n const candidatePart: Record<string, unknown> = {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n };\n // Omit the bindings key entirely when empty — \"no bindings\" is represented\n // as key absence; an empty array is not a valid value in the format contract.\n if (this.bindings.length > 0) {\n candidatePart.bindings = this.bindings.map((b) => ({ ...b }));\n }\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [candidatePart],\n };\n // Validation before any mutation. The synthetic candidate always places the\n // part at parts[0], so the validator emits paths like \"parts[0].bindings[i]\".\n // Rewrite that prefix to name the real target so the surfaced error is\n // actionable (\"parts.\"part-a\".bindings[i]\" rather than \"parts[0].bindings[i]\").\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n throw new IkiFormatError(\n e.message.replace(/^parts\\[0\\]/, `parts.\"${this.partId}\"`),\n );\n }\n throw e;\n }\n\n // Resolution after validation so an unknown partId throws with a\n // path-qualified message (findPart throws) but only after the bindings\n // themselves are confirmed structurally valid.\n const part = doc.findPart(this.partId);\n if (!this.captured) {\n // Preserve the original absent-vs-empty distinction.\n this.prevBindings =\n part.bindings === undefined\n ? undefined\n : part.bindings.map((b) => ({ ...b }));\n this.captured = true;\n }\n if (this.bindings.length > 0) {\n // Assign a fresh deep copy — model must never alias the command's stored array.\n part.bindings = this.bindings.map((b) => ({ ...b }));\n } else {\n // Delete the key on empty: keeps the model shape minimal and correctly\n // represents \"no bindings\" as an absent key rather than an empty array.\n delete part.bindings;\n }\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n if (this.prevBindings === undefined) {\n delete part.bindings;\n } else {\n // Assign a fresh deep copy — never alias the captured array so re-apply\n // after undo cannot corrupt the saved prior value.\n part.bindings = this.prevBindings.map((b) => ({ ...b }));\n }\n }\n}\n\n/**\n * Attach a part to a deformer, or detach it (`newDeformerId === undefined`).\n * Calls {@link validatePartAttach} FIRST so invalid attachments (warp without\n * mesh, unknown ids) throw before any capture or mutation.\n *\n * Absent-vs-present distinction mirrors {@link SetDeformerParent}: captures\n * both the prior `deformer` value and whether the key was present, so `invert`\n * can delete the key rather than assigning `undefined`.\n */\nexport class SetPartDeformer implements EditCommand {\n readonly label = \"Set part deformer\";\n private captured = false;\n private prevDeformer: string | undefined = undefined;\n private prevHadDeformer = false;\n\n constructor(\n private readonly partId: string,\n private readonly newDeformerId: string | undefined,\n ) {}\n\n apply(doc: EditorDocument): void {\n // Validate FIRST — throws before capture/mutate on any violation.\n validatePartAttach(\n doc.getModel().deformers ?? [],\n this.partId,\n doc.getModel().parts,\n this.newDeformerId,\n );\n const part = doc.findPart(this.partId);\n if (!this.captured) {\n this.prevHadDeformer = Object.prototype.hasOwnProperty.call(\n part,\n \"deformer\",\n );\n this.prevDeformer = part.deformer;\n this.captured = true;\n }\n if (this.newDeformerId !== undefined) {\n part.deformer = this.newDeformerId;\n } else {\n delete part.deformer;\n }\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n if (this.prevHadDeformer) {\n part.deformer = this.prevDeformer;\n } else {\n delete part.deformer;\n }\n }\n}\n\n/**\n * Return true if the deformer identified by `deformerId` exists in the model\n * and has `kind === \"warp\"`. Used by SetPartMesh to detect warp-deformer\n * attachment without importing reparent.ts internals.\n */\nfunction isWarpDeformer(model: IkiModel, deformerId: string): boolean {\n const d = (model.deformers ?? []).find((x) => x.id === deformerId);\n return d?.kind === \"warp\";\n}\n\n/**\n * Add, regenerate, or remove the triangle mesh on a part.\n *\n * - `mesh !== undefined` → add or replace the mesh, registering the\n * unit-square base UVs in the side-table so {@link EditorDocument.applyAtlas}\n * can remap them later.\n * - `mesh === undefined` → delete `part.mesh` and remove the side-table entry.\n *\n * Fails fast (BEFORE any mutation) on warp-topology violations:\n * - REMOVE while `part.warps` is present (even empty) or the part is\n * attached to a warp deformer — the format rejects any `warps` key once\n * the mesh is gone.\n * - ADD/REPLACE while `part.warps` has authored offsets (`length > 0`) —\n * regenerating the mesh invalidates offset positions silently; the user\n * must remove the warps first.\n *\n * The remove guard checks PRESENCE of `part.warps` (not length) while the\n * add/replace guard checks LENGTH > 0. This asymmetry is intentional: the\n * format allows `warps: []` only when a mesh exists, so any present key\n * (even empty) would become invalid after mesh removal; but replacing a mesh\n * under an empty `warps: []` is harmless because there are no authored offsets.\n */\nexport class SetPartMesh implements EditCommand {\n readonly label = \"Set part mesh\";\n private readonly mesh: IkiMesh | undefined;\n private captured = false;\n private prevHadMesh = false;\n private prevMesh: IkiMesh | undefined;\n private prevBaseMeshUvs: number[] | undefined;\n\n constructor(\n private readonly partId: string,\n mesh: IkiMesh | undefined,\n ) {\n // Clone on construction — prevents caller mutation from corrupting apply/redo.\n this.mesh = mesh === undefined ? undefined : structuredClone(mesh);\n }\n\n apply(doc: EditorDocument): void {\n // (a) Resolve the live part up front — unlike SetPartBindings, which resolves\n // after parseIkiModel, we need the live part here because the warp-topology\n // guards at step (c) inspect part.warps / part.deformer before any mutation.\n const part = doc.findPart(this.partId);\n\n // (b) Structural validation — only needed when adding or replacing a mesh.\n // Build a NARROW synthetic candidate carrying only the new mesh so that\n // unrelated in-flight parts with NaN values cannot cause false failures.\n if (this.mesh !== undefined) {\n const candidatePart = {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n mesh: structuredClone(this.mesh),\n };\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [candidatePart],\n };\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n throw new IkiFormatError(\n e.message.replace(/^parts\\[0\\]/, `parts.\"${this.partId}\"`),\n );\n }\n throw e;\n }\n }\n\n // (c) Warp-topology fail-fast — BEFORE any mutation, after structural validation.\n // The two paths key on DIFFERENT predicates; this asymmetry is intentional\n // (see class JSDoc above).\n const attachedToWarp =\n part.deformer !== undefined &&\n isWarpDeformer(doc.getModel(), part.deformer);\n\n if (this.mesh === undefined) {\n // REMOVE: guard on warps PRESENCE (even empty) OR warp-deformer attachment.\n // The format rejects ANY present `warps` key once the mesh is gone, so even\n // an empty array would make toIkiModel() throw.\n if (part.warps !== undefined || attachedToWarp) {\n throw new IkiFormatError(\n `parts.\"${this.partId}\": cannot remove mesh — part has warps or is attached to a warp deformer; remove its warps / detach from the warp deformer first`,\n );\n }\n // Clip-mask guard — the format requires a clip mask to be a mesh part, so\n // stripping the mesh from a referenced mask would dangle the ref and fail\n // toIkiModel(). Mirrors the DeletePart clip-mask guard.\n const masker = doc\n .getModel()\n .parts.find(\n (p) => p.id !== this.partId && p.clip?.masks.includes(this.partId),\n );\n if (masker) {\n throw new IkiFormatError(\n `parts.\"${this.partId}\": cannot remove mesh — used as a clip mask by part \"${masker.id}\" (masks require a mesh); remove its clip first`,\n );\n }\n } else {\n // ADD/REPLACE: guard on authored offsets (length > 0). An empty warps: []\n // has no offsets to invalidate, so replacing the mesh under it is harmless.\n if ((part.warps?.length ?? 0) > 0) {\n throw new IkiFormatError(\n `parts.\"${this.partId}\": cannot regenerate mesh — part has warps whose offsets are bound to the current rest mesh; remove its warps first`,\n );\n }\n }\n\n // (d) Mutate + side-table maintenance.\n\n // (i) Single first-apply capture block — captures BOTH prevMesh and\n // prevBaseMeshUvs together, BEFORE any mutation. captureBaseMeshUvs has\n // a side effect (registers current mesh.uvs); step (iii) overwrites it.\n if (!this.captured) {\n this.prevHadMesh = part.mesh !== undefined;\n this.prevMesh = part.mesh ? structuredClone(part.mesh) : undefined;\n this.prevBaseMeshUvs = doc.captureBaseMeshUvs(this.partId);\n this.captured = true;\n }\n // Redo: do NOT re-capture (would clobber the saved prior). The mutation\n // below is fully reconstructable from this.mesh + this.partId.\n\n // (ii) Apply the model mutation.\n if (this.mesh !== undefined) {\n // Compute stored UVs: if the part has an active texture, remap the\n // unit-square base UVs into the texture's atlas sub-rectangle.\n const storedUvs =\n part.texture !== undefined\n ? remapMeshUvsToRect(this.mesh.uvs, part.texture.uv)\n : this.mesh.uvs.slice();\n part.mesh = {\n vertices: this.mesh.vertices.slice(),\n uvs: storedUvs,\n indices: this.mesh.indices.slice(),\n };\n } else {\n delete part.mesh;\n }\n\n // (iii) Re-register the side-table to the correct final state, overwriting\n // the (i) read's incidental re-registration. Write ONLY via\n // restoreBaseMeshUvs — never via a new setBaseMeshUvs API.\n if (this.mesh !== undefined) {\n // Register the UNIT-SQUARE base (not the texture-remapped storedUvs) so\n // applyAtlas can always derive correct atlas-space UVs from the base.\n doc.restoreBaseMeshUvs(this.partId, this.mesh.uvs.slice());\n } else {\n doc.restoreBaseMeshUvs(this.partId, undefined);\n }\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n // Restore the mesh, preserving the absent-vs-present distinction.\n // applyAtlas (and texture changes generally) are NON-undoable and do NOT\n // clear the undo stack. So by the time undo() is called, part.texture may\n // have been changed by a later applyAtlas that this command never saw. To\n // avoid restoring stale texture-space UVs, rebuild uvs from the captured\n // unit-square base against the CURRENT texture rect rather than trusting\n // prevMesh.uvs verbatim.\n if (this.prevHadMesh) {\n // A mesh part ALWAYS has a registered unit-square base under the invariant\n // (applyAtlas preflights requireBaseUvs for every mesh part). If the base is\n // absent here the side-table invariant is broken — fail fast rather than\n // silently restoring stale texture-space uvs that would corrupt rendering.\n if (this.prevBaseMeshUvs === undefined) {\n throw new Error(\n `parts.\"${this.partId}\": cannot invert SetPartMesh — no base mesh uvs captured for a mesh part (broken side-table invariant)`,\n );\n }\n const restored = structuredClone(this.prevMesh!);\n // Remap the unit-square base into the current texture rect (if any).\n restored.uvs =\n part.texture !== undefined\n ? remapMeshUvsToRect(this.prevBaseMeshUvs, part.texture.uv)\n : this.prevBaseMeshUvs.slice();\n part.mesh = restored;\n } else {\n delete part.mesh;\n }\n // Restore the side-table to the exact prior state (unit-square base).\n doc.restoreBaseMeshUvs(this.partId, this.prevBaseMeshUvs);\n }\n}\n\n/**\n * Validate a candidate `physics` array against the model's declared parameters\n * via a NARROW synthetic model — full `parameters` + the full candidate physics\n * array + one trivial part. Mirrors {@link SetPartBindings}' synthetic-candidate\n * (avoids false-positives from unrelated in-flight NaN part numerics) but carries\n * the FULL physics array so the cross-rig rules (dup id / dup output / feedback)\n * run. On `IkiFormatError`, rewrite the failing `physics[n]` path to name the rig\n * AT THE FAILING INDEX — a cross-rig failure can surface at a different index than\n * the edited rig, so the rewrite follows the message index, not the command target.\n */\nfunction validatePhysicsCandidate(\n doc: EditorDocument,\n candidatePhysics: IkiPhysics[],\n): void {\n const candidatePart: Record<string, unknown> = {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n };\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [candidatePart],\n deformers: doc.getModel().deformers,\n physics: candidatePhysics,\n physicsChains: doc.getModel().physicsChains,\n };\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n const m = e.message.match(/^physics\\[(\\d+)\\]/);\n const rigId = m ? candidatePhysics[Number(m[1])]?.id : undefined;\n if (rigId !== undefined) {\n throw new IkiFormatError(\n e.message.replace(/^physics\\[\\d+\\]/, `physics.\"${rigId}\"`),\n );\n }\n }\n throw e;\n }\n}\n\n/**\n * Add a physics rig to `model.physics`. Mirrors {@link AddDeformer}: clone on\n * construction, cheap friendly duplicate-id pre-check, full synthetic-candidate\n * validation before mutating, capture the absent-vs-present `physics` state once,\n * and on invert delete the key when the array empties back to its prior absence.\n */\nexport class AddPhysicsRig implements EditCommand {\n readonly label = \"Add physics rig\";\n private readonly rig: IkiPhysics;\n private captured = false;\n private prevPhysicsAbsent = false;\n\n constructor(rig: IkiPhysics) {\n // Deep clone — input/output are nested objects a shallow spread would alias.\n this.rig = structuredClone(rig);\n }\n\n apply(doc: EditorDocument): void {\n const model = doc.getModel();\n // (a) Friendly duplicate-id pre-check (the format check from validate.ts is\n // the real guard; this surfaces an actionable message before validate).\n if ((model.physics ?? []).some((r) => r.id === this.rig.id)) {\n throw new Error(\n `physics: id \"${this.rig.id}\" collides with an existing physics rig id`,\n );\n }\n // (b) Full-physics synthetic validation with the rig appended.\n validatePhysicsCandidate(doc, [\n ...(model.physics ?? []),\n structuredClone(this.rig),\n ]);\n // (c) Capture-once, then mutate with a fresh clone.\n if (!this.captured) {\n this.prevPhysicsAbsent = model.physics === undefined;\n this.captured = true;\n }\n if (model.physics === undefined) {\n model.physics = [];\n }\n model.physics.push(structuredClone(this.rig));\n }\n\n invert(doc: EditorDocument): void {\n const model = doc.getModel();\n const arr = model.physics;\n if (!arr) return;\n const i = arr.findIndex((r) => r.id === this.rig.id);\n if (i !== -1) arr.splice(i, 1);\n if (this.prevPhysicsAbsent && arr.length === 0) {\n delete model.physics;\n }\n }\n}\n\n/**\n * Delete a physics rig by id. Mirrors {@link DeleteDeformer}: resolve/validate\n * first, capture the removed rig + its index once, splice. Removing the LAST rig\n * deletes the `physics` key to keep the exported shape minimal; invert re-inserts\n * at the original index (recreating the array if it was deleted).\n */\nexport class DeletePhysicsRig implements EditCommand {\n readonly label = \"Delete physics rig\";\n private captured = false;\n private removed!: IkiPhysics;\n private index!: number;\n\n constructor(private readonly rigId: string) {}\n\n apply(doc: EditorDocument): void {\n const rig = doc.findPhysicsRig(this.rigId); // throws if unknown\n const arr = doc.getModel().physics!;\n const i = arr.indexOf(rig);\n if (!this.captured) {\n this.removed = structuredClone(rig);\n this.index = i;\n this.captured = true;\n }\n arr.splice(i, 1);\n // Minimal exported shape: drop the key once the last rig is gone.\n if (arr.length === 0) {\n delete doc.getModel().physics;\n }\n }\n\n invert(doc: EditorDocument): void {\n const model = doc.getModel();\n (model.physics ??= []).splice(this.index, 0, structuredClone(this.removed));\n }\n}\n\n/**\n * Replace a physics rig in place (tuning). Mirrors {@link SetDeformerBindings}\n * but DEEP-clones the nested `input`/`output` (a shallow spread would alias them).\n * Forbids rename (`rig.id` must equal the target `rigId`) — this command tunes a\n * rig, never re-keys it. Validates the whole candidate (the edited rig swapped in\n * at its index) so cross-rig rules still run, then captures the prior rig once.\n */\nexport class SetPhysicsRig implements EditCommand {\n readonly label = \"Set physics rig\";\n private readonly rig: IkiPhysics;\n private captured = false;\n private prevRig!: IkiPhysics;\n\n constructor(\n private readonly rigId: string,\n rig: IkiPhysics,\n ) {\n this.rig = structuredClone(rig);\n }\n\n apply(doc: EditorDocument): void {\n // No-rename guard — fail before mutating.\n if (this.rig.id !== this.rigId) {\n throw new Error(\n `physics.\"${this.rigId}\": cannot change rig id to \"${this.rig.id}\" (rename unsupported)`,\n );\n }\n const model = doc.getModel();\n const i = (model.physics ?? []).findIndex((r) => r.id === this.rigId);\n if (i === -1) {\n throw new Error(`physics: no physics rig with id \"${this.rigId}\"`);\n }\n // Validate a candidate with the edited rig swapped in at its index.\n const candidate = model.physics!.map((r, idx) =>\n idx === i ? structuredClone(this.rig) : r,\n );\n validatePhysicsCandidate(doc, candidate);\n if (!this.captured) {\n this.prevRig = structuredClone(model.physics![i]);\n this.captured = true;\n }\n model.physics![i] = structuredClone(this.rig);\n }\n\n invert(doc: EditorDocument): void {\n const arr = doc.getModel().physics;\n if (!arr) return;\n const i = arr.findIndex((r) => r.id === this.rigId);\n if (i !== -1) arr[i] = structuredClone(this.prevRig);\n }\n}\n","import type { IkiGridKeyform } from \"@ikijs/format\";\n\n/**\n * Pure, grid-size-agnostic keyform/offset math for authoring a warp-deformer\n * grid by dragging. No DOM, no `@ikijs/engine` — the load-bearing testable core.\n * Constraints derive only from the input array lengths, never the sample grid.\n */\n\n/**\n * Interpolate the grid offsets at `value`, mirroring the engine's\n * `accumulateKeyformOffsets` clamp+lerp semantics: clamp to the first/last\n * keyform (NO extrapolation) and linearly interpolate the bracketing pair.\n * Returns a NEW array of length `keyforms[0].offsets.length`. Throws on empty.\n */\nexport function interpolateGridOffsets(\n keyforms: { value: number; offsets: number[] }[],\n value: number,\n): number[] {\n if (keyforms.length === 0) {\n throw new Error(\"interpolateGridOffsets: keyforms must be non-empty\");\n }\n\n if (value <= keyforms[0].value) {\n return [...keyforms[0].offsets];\n }\n const last = keyforms[keyforms.length - 1];\n if (value >= last.value) {\n return [...last.offsets];\n }\n\n // Find the bracketing pair (keyforms are small in practice).\n let lo = keyforms[0];\n let hi = keyforms[1];\n for (let k = 1; k < keyforms.length - 1; k++) {\n if (keyforms[k].value <= value) {\n lo = keyforms[k];\n hi = keyforms[k + 1];\n }\n }\n const t = (value - lo.value) / (hi.value - lo.value);\n return lo.offsets.map((loOff, i) => loOff + (hi.offsets[i] - loOff) * t);\n}\n\n/**\n * Per-control-point delta of the dragged grid from the rest grid: for each\n * point `i`, `(draggedX_i - restX_i, draggedY_i - restY_i)`. The DOM layer\n * assembles the full `restFrameDraggedPoints` (including untouched points), so\n * this is a straight subtract — no prior-offset blending.\n *\n * Both arrays must have the SAME length and that length must be even (x,y\n * pairs). Returns a NEW array of length `restPoints.length`.\n */\nexport function computeGridOffsets(\n restPoints: number[],\n restFrameDraggedPoints: number[],\n): number[] {\n if (restPoints.length !== restFrameDraggedPoints.length) {\n throw new Error(\n `computeGridOffsets: restFrameDraggedPoints length ${restFrameDraggedPoints.length} must equal restPoints length ${restPoints.length}`,\n );\n }\n if (restPoints.length % 2 !== 0) {\n throw new Error(\n `computeGridOffsets: restPoints length ${restPoints.length} must be even (x,y pairs)`,\n );\n }\n return restPoints.map((rest, i) => restFrameDraggedPoints[i] - rest);\n}\n\n/**\n * Insert or replace the keyform at `value`, returning a NEW array. If a keyform\n * already exists with an exact-match `value`, REPLACE its offsets (with a copy);\n * otherwise INSERT `{ value, offsets: [...offsets] }` at the position that keeps\n * the array strictly ascending by value. The input array and its keyform objects\n * are never mutated, and `offsets` is copied so the result never aliases the\n * caller's array.\n *\n * Deliberately RANGE-FREE — a generic, reusable array op. Value-range\n * enforcement is the command's job, not this helper's.\n */\nexport function upsertGridKeyform(\n keyforms: IkiGridKeyform[],\n value: number,\n offsets: number[],\n): IkiGridKeyform[] {\n const result = keyforms.map((kf) => ({\n value: kf.value,\n offsets: [...kf.offsets],\n }));\n const existing = result.findIndex((kf) => kf.value === value);\n if (existing !== -1) {\n result[existing] = { value, offsets: [...offsets] };\n return result;\n }\n const insertAt = result.findIndex((kf) => kf.value > value);\n const entry: IkiGridKeyform = { value, offsets: [...offsets] };\n if (insertAt === -1) {\n result.push(entry);\n } else {\n result.splice(insertAt, 0, entry);\n }\n return result;\n}\n","import type { IkiDeformer, IkiPart, IkiPhysicsChain } from \"@ikijs/format\";\n\n/**\n * Pure, DOM-free validation helpers for deformer reparenting and part attachment.\n * Each function throws a path-qualified plain Error on rejection and returns void\n * on success. Neither function mutates the input arrays or objects.\n */\n\nfunction kindOf(d: IkiDeformer): \"warp\" | \"matrix\" {\n return d.kind === \"warp\" ? \"warp\" : \"matrix\";\n}\n\n/**\n * Validate that reparenting `deformerId` under `newParentId` keeps the deformer\n * hierarchy valid. Pass `newParentId === undefined` to move to root (always legal).\n * Checks: existence, self-reference, undeclared parent, kind constraint (a warp\n * deformer cannot be the parent of another warp deformer), a matrix deformer's\n * pivot inside its new warp parent's rest grid, and cycle detection via the\n * proposed edge.\n */\nexport function validateDeformerReparent(\n deformers: IkiDeformer[],\n deformerId: string,\n newParentId: string | undefined,\n): void {\n // (1) Target deformer must exist.\n const target = deformers.find((d) => d.id === deformerId);\n if (target === undefined) {\n throw new Error(`deformers: no deformer with id \"${deformerId}\"`);\n }\n\n // (2) Root is always legal.\n if (newParentId === undefined) return;\n\n // (3) Self-reference.\n if (newParentId === deformerId) {\n throw new Error(\n `deformers.\"${deformerId}\".parent \"${newParentId}\" is a self-reference`,\n );\n }\n\n // (4) Parent must be declared.\n const parent = deformers.find((d) => d.id === newParentId);\n if (parent === undefined) {\n throw new Error(\n `deformers.\"${deformerId}\".parent \"${newParentId}\" is not a declared deformer`,\n );\n }\n\n // (5) A warp deformer cannot be nested under another warp deformer.\n if (kindOf(parent) === \"warp\" && kindOf(target) === \"warp\") {\n throw new Error(\n `deformers.\"${deformerId}\".parent \"${newParentId}\" must be a matrix deformer (warp deformers cannot be nested under a warp deformer)`,\n );\n }\n\n // (6) A matrix deformer's pivot must lie inside its warp parent's rest grid,\n // as the format requires. Refusing here keeps the bad edge out of the\n // model and the undo stack; a pivot moved out later (typed digit by\n // digit through invalid values) is still left to the export check.\n if (parent.kind === \"warp\" && target.kind !== \"warp\") {\n const { pivot } = target;\n // The same corners the format validator reads (row 0 is the top, column 0\n // the left), so a grid with in-tolerance jitter cannot pass here and then\n // fail at export.\n const { cols, rows, points } = parent.grid;\n const xMin = points[0];\n const xMax = points[2 * cols];\n const yMax = points[1];\n const yMin = points[rows * (cols + 1) * 2 + 1];\n if (pivot.x < xMin || pivot.x > xMax || pivot.y < yMin || pivot.y > yMax) {\n throw new Error(\n `deformers.\"${deformerId}\".pivot (${pivot.x}, ${pivot.y}) lies outside its warp parent \"${newParentId}\" rest grid x ${xMin}..${xMax}, y ${yMin}..${yMax}`,\n );\n }\n }\n\n // (7) Cycle detection: build parentOf from current state, then override with\n // the proposed edge, and walk from deformerId following the chain.\n const parentOf = new Map<string, string>();\n for (const d of deformers) {\n if (d.parent !== undefined) parentOf.set(d.id, d.parent);\n }\n // Override with the proposed edge.\n parentOf.set(deformerId, newParentId);\n\n const visited = new Set<string>();\n let cur: string | undefined = deformerId;\n while (cur !== undefined) {\n if (visited.has(cur)) {\n throw new Error(\n `deformers: reparenting \"${deformerId}\" under \"${newParentId}\" would create a cycle`,\n );\n }\n visited.add(cur);\n cur = parentOf.get(cur);\n }\n}\n\n/**\n * Validate that deleting `deformerId` is safe. Throws when the deformer does\n * not exist, when another deformer is parented to it (must be reparented or\n * detached first), when a part is attached to it (must be detached first), or\n * when a physics chain anchors to it (must be re-anchored or deleted first).\n *\n * Every id that can reference a deformer must be covered here: the format\n * validator rejects a dangling reference at export, so a delete this function\n * lets through does not fail now — it strands the document in a state\n * `toIkiModel()` refuses.\n *\n * Note: there is no validatePartDelete here, but NOT because parts are\n * unreferenced — `clip.masks` names parts by id. That invariant is enforced\n * closer to the edits that could break it: `DeletePart` refuses to remove a\n * part still used as a mask, and `SetPartMesh` refuses to strip the mesh off\n * one (masks must be mesh parts). No command creates or edits `clip`.\n */\nexport function validateDeformerDelete(\n deformers: IkiDeformer[],\n parts: IkiPart[],\n physicsChains: IkiPhysicsChain[],\n deformerId: string,\n): void {\n // (1) Target deformer must exist.\n const target = deformers.find((d) => d.id === deformerId);\n if (target === undefined) {\n throw new Error(`deformers: no deformer with id \"${deformerId}\"`);\n }\n\n // (2) No other deformer may be parented to it.\n const childDeformer = deformers.find((d) => d.parent === deformerId);\n if (childDeformer !== undefined) {\n throw new Error(\n `deformers.\"${deformerId}\": cannot delete — deformer \"${childDeformer.id}\" is parented to it; reparent or detach it first`,\n );\n }\n\n // (3) No part may be attached to it.\n const attachedPart = parts.find((p) => p.deformer === deformerId);\n if (attachedPart !== undefined) {\n throw new Error(\n `deformers.\"${deformerId}\": cannot delete — part \"${attachedPart.id}\" is attached to it; detach it first`,\n );\n }\n\n // (4) No physics chain may anchor to it.\n const anchoredChain = physicsChains.find(\n (c) => c.anchorDeformer === deformerId,\n );\n if (anchoredChain !== undefined) {\n throw new Error(\n `deformers.\"${deformerId}\": cannot delete — physics chain \"${anchoredChain.id}\" anchors to it; re-anchor or delete the chain first`,\n );\n }\n}\n\n/**\n * Validate that attaching part `partId` to deformer `newDeformerId` is valid.\n * Pass `newDeformerId === undefined` to detach (always legal).\n * Checks: part existence, undeclared deformer, and mesh-required-for-warp.\n */\nexport function validatePartAttach(\n deformers: IkiDeformer[],\n partId: string,\n parts: IkiPart[],\n newDeformerId: string | undefined,\n): void {\n // (1) Part must exist.\n const part = parts.find((p) => p.id === partId);\n if (part === undefined) {\n throw new Error(`parts: no part with id \"${partId}\"`);\n }\n\n // (2) Detach is always legal.\n if (newDeformerId === undefined) return;\n\n // (3) Deformer must be declared.\n const deformer = deformers.find((d) => d.id === newDeformerId);\n if (deformer === undefined) {\n throw new Error(\n `parts.\"${partId}\".deformer \"${newDeformerId}\" is not a declared deformer`,\n );\n }\n\n // (4) Warp deformer requires a mesh on the part.\n if (kindOf(deformer) === \"warp\" && part.mesh === undefined) {\n throw new Error(\n `parts.\"${partId}\".deformer \"${newDeformerId}\" is a warp deformer and requires a mesh`,\n );\n }\n}\n","/**\n * Alpha bounding-box scan shared by every auto-rig ingestion path.\n *\n * The scan itself is environment-free — it only needs indexable RGBA bytes — so\n * a browser editor (canvas `ImageData`) and the Node MCP server (a `sharp`\n * raw buffer) run the SAME code instead of two copies that have to be kept\n * byte-identical by hand. Only decoding differs between them.\n */\n\n/** Alpha at or above this counts as coverage; below it is treated as empty. */\nexport const ALPHA_BBOX_THRESHOLD = 8;\n\n/** Top-left origin, +y down — image space, not model space. */\nexport interface AlphaBbox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/**\n * Tight bounding box of every pixel with alpha >= {@link ALPHA_BBOX_THRESHOLD},\n * expanded 1px on each side (clamped to the image) for AA / extrude margin.\n *\n * Returns `null` when no pixel passes the threshold, leaving the \"empty layer\"\n * error to the caller: each ingestion path reports it with its own error type\n * and message.\n */\nexport function detectAlphaBbox(\n rgba: ArrayLike<number>,\n width: number,\n height: number,\n): AlphaBbox | null {\n let minX = width;\n let maxX = -1;\n let minY = height;\n let maxY = -1;\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const alpha = rgba[(y * width + x) * 4 + 3];\n if (alpha >= ALPHA_BBOX_THRESHOLD) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n }\n\n if (maxX === -1) return null;\n\n // Expand 1px each side, clamped to image bounds; the x2/y2 clamps make w/h\n // implicitly in-bounds (no separate w/h clamp needed).\n const x = Math.max(0, minX - 1);\n const y = Math.max(0, minY - 1);\n const x2 = Math.min(width - 1, maxX + 1);\n const y2 = Math.min(height - 1, maxY + 1);\n\n return { x, y, w: x2 - x + 1, h: y2 - y + 1 };\n}\n","/**\n * The alpha rules a layer set is measured by, and the pre-rig measurement of\n * that set, in one DOM-free copy — the way `detectAlphaBbox` is one.\n *\n * Both auto-rig hosts — the editor app (canvas `getImageData`) and\n * `@ikijs/mcp`'s `auto_rig_from_layers` (a `sharp` raw buffer) — hand\n * `createLayerSetMeasurer` the RGBA they decoded and rig what it measures, and\n * `@ikijs/mcp`'s other tools (`measure_turn_reference`, `measure_layers`, the\n * composer) read the same rules. Two copies would have to be kept identical by\n * hand, or the head a render measures back, or the nose core the composer\n * placed, would part from the one the rig was fitted to. Only decoding differs\n * between the hosts.\n */\n\nimport { detectAlphaBbox } from \"./alpha-bbox\";\nimport type { IrisStrand, LayerInput } from \"./auto-rig\";\n\n/** Half-height of the row band the head span is taken over, in px. Fixed at\n * ±10 rows rather than scaled to the image, and that is the convention: any\n * other measurement of head width meant to be compared with the one\n * `@ikijs/mcp`'s `measure_turn_reference` takes off a render — one taken off\n * layer alpha, a hand script — has to span the same band. Shared by that tool\n * and `createLayerSetMeasurer`, so the head it spans off the layers' alpha\n * union spans this band too. */\nexport const HEAD_BAND = 10;\n\n/** Alpha at or above this is opaque. Shared by `@ikijs/mcp`'s\n * `measure_turn_reference`, whose \"alpha\" foreground rule reads an engine\n * render's silhouette by it, and by the layer-alpha silhouette\n * `createLayerSetMeasurer` measures the head on, which has to follow that\n * rule to be comparable with a render. */\nexport const ALPHA_OPAQUE = 128;\n\n/**\n * A layer's dense core: the tight box of its pixels at alpha ≥ ALPHA_OPAQUE,\n * not grown. A soft-alpha part (a nose drawn as a shaded bump) is mostly\n * feather, and the core is the drawing a viewer reads inside it — `@ikijs/mcp`'s\n * composer sizes and places the nose by it, and `createLayerSetMeasurer` reads\n * the same core as the nose's `LayerInput.denseCore`, its turn landmark. It is\n * not the crop: that stays the alpha ≥ 8 box grown by 1 px (`detectAlphaBbox`).\n * `null` when no pixel reaches the threshold, a part painted wholly\n * translucent. A core that is a speck of its part (`isSpeckCore`) is not the\n * drawing either, and both readers fall back to the whole part, as they do for\n * `null`.\n */\nexport function denseCoreOf(\n rgba: ArrayLike<number>,\n width: number,\n height: number,\n): { x: number; y: number; w: number; h: number } | null {\n let minX = width;\n let minY = height;\n let maxX = -1;\n let maxY = -1;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n if (rgba[(y * width + x) * 4 + 3] >= ALPHA_OPAQUE) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n }\n if (maxX < 0) return null;\n return { x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1 };\n}\n\n/**\n * The fraction of its part's width, or of its height, under which a dense core\n * is a speck (`isSpeckCore`). Measured core/part ratios, width / height: the\n * hero's composed nose 0.72 / 0.76 (core 39×63 in a 54×83 crop), three\n * generated shaded-bump noses (the plugin's 0.11 nose prompt) 0.75–0.85 /\n * 0.79–0.91, `@ikijs/mcp`'s `writeSoftNose` test fixture 0.56 / 0.63 and its\n * `writeSoftNoseLayers` 0.40 / 0.40, a nostril mark ≤ 0.1. So the line sits at\n * least 1.6× under every real nose and fixture, and 2.5× over a speck. At the\n * line, sizing by the core would scale the whole part to 4× its layout width,\n * the largest blow-up `@ikijs/mcp`'s composer still accepts.\n */\nexport const SPECK_CORE_FRACTION = 0.25;\n\n/**\n * Whether a dense core is a speck of its part: narrower than\n * SPECK_CORE_FRACTION of the part's width, or shorter than that fraction of\n * its height (strictly `<`). Either dimension counts, because the core does\n * more than size a nose: its bottom row is the tip the composer places, and\n * its top-centre the rig's tilt pivot, so a sliver misplaces the nose as\n * surely as a speck mis-sizes it. A speck is a lone nostril mark or highlight,\n * not the drawing, and every reader falls back to the whole part: `@ikijs/mcp`'s\n * compose sizes and places its trimmed source part whole, and\n * `createLayerSetMeasurer` hands the rig no core, so the crop stands in.\n *\n * The two apply it to different pixels — compose to the source part before\n * resampling, the rig and `measure_layers` to the composed layer against its\n * crop — so their verdicts can part, but only for a core within about a\n * resampled pixel of the line, or one resampling pushes across ALPHA_OPAQUE.\n * Compose's report carries its source verdict when that was a speck, and\n * otherwise what the composed layer shows, so it warns of a parting either\n * way; `measure_layers` reports the layer alone.\n */\nexport function isSpeckCore(\n core: { w: number; h: number },\n part: { w: number; h: number },\n): boolean {\n return (\n core.w < SPECK_CORE_FRACTION * part.w ||\n core.h < SPECK_CORE_FRACTION * part.h\n );\n}\n\n/**\n * Outermost set pixels of `mask` across the row band `rowLo..rowHi` (clamped\n * to the image) — the silhouette span at that height. An empty band returns\n * `left > right`, which every caller has to check for.\n *\n * Shared by `@ikijs/mcp`'s `measure_turn_reference`, which spans a render's\n * head with it, and `createLayerSetMeasurer`, which spans the layers' alpha\n * union: the two heads are compared, so they have to be spanned the same way.\n */\nexport function foregroundSpan(\n mask: Uint8Array,\n width: number,\n height: number,\n rowLo: number,\n rowHi: number,\n): { left: number; right: number } {\n let left = width;\n let right = -1;\n for (let y = Math.max(0, rowLo); y <= Math.min(height - 1, rowHi); y++) {\n for (let x = 0; x < width; x++) {\n if (!mask[y * width + x]) continue;\n if (x < left) left = x;\n if (x > right) right = x;\n }\n }\n return { left, right };\n}\n\n/**\n * Half of a silhouette span, in px. The span is INCLUSIVE — `left` and `right`\n * are both foreground columns — so the head is `right - left + 1` px wide.\n * Shared by `@ikijs/mcp`'s `measure_turn_reference` and\n * `createLayerSetMeasurer`: the two head half-widths are compared against each\n * other, so they cannot be halved differently.\n */\nexport function headHalfOf(span: { left: number; right: number }): number {\n return (span.right - span.left + 1) / 2;\n}\n\n/** One decoded layer, as a host hands it to `LayerSetMeasurer.add`. */\nexport interface RgbaLayer {\n /** Canonical role, e.g. \"eye_L\" — the host has run `parseLayerRoles` on\n * the set already. */\n role: string;\n /** Original file name: the `LayerInput`'s own, and named in errors. */\n fileName: string;\n /** Straight-alpha RGBA, stride 4, `canvas.width × canvas.height` pixels —\n * canvas `ImageData.data` or a `sharp` raw buffer alike. */\n rgba: ArrayLike<number>;\n}\n\n/** A pixel darker than this share of the plate's median skin luminance is\n * line work: the jaw's outline, not its shading. */\nconst DARK_SHARE = 0.55;\n\n/**\n * The face plate's jaw line, per crop column: going down from the plate's\n * widest row, the canvas row of the last pixel of the first dark stroke met\n * (the jaw's outline where a neck runs on below it), or −1 where the column\n * leaves the paint first. `undefined` when no column meets a stroke — art\n * with no line work, which the generator then reads off its outline alone.\n */\nfunction jawRowsOf(\n rgba: ArrayLike<number>,\n canvasW: number,\n bbox: { x: number; y: number; w: number; h: number },\n rowLeft: Int32Array,\n rowRight: Int32Array,\n): number[] | undefined {\n const lum = (p: number) =>\n 0.299 * rgba[p * 4] + 0.587 * rgba[p * 4 + 1] + 0.114 * rgba[p * 4 + 2];\n const hist = new Uint32Array(256);\n let count = 0;\n let widest = bbox.y;\n let widestSpan = -1;\n for (let y = bbox.y; y < bbox.y + bbox.h; y++) {\n const span = rowRight[y] - rowLeft[y];\n if (span >= widestSpan) {\n widestSpan = span;\n widest = y;\n }\n for (let x = bbox.x; x < bbox.x + bbox.w; x++) {\n const p = y * canvasW + x;\n if (rgba[p * 4 + 3] < ALPHA_OPAQUE) continue;\n hist[Math.min(255, Math.round(lum(p)))]++;\n count++;\n }\n }\n if (count === 0) return undefined;\n let median = 0;\n for (let acc = 0; median < 255; median++) {\n acc += hist[median];\n if (acc * 2 >= count) break;\n }\n const dark = DARK_SHARE * median;\n const out: number[] = [];\n let found = false;\n for (let x = bbox.x; x < bbox.x + bbox.w; x++) {\n let row = -1;\n for (let y = widest + 1; y < bbox.y + bbox.h; y++) {\n const p = y * canvasW + x;\n if (rgba[p * 4 + 3] < ALPHA_OPAQUE) break;\n if (lum(p) >= dark) continue;\n let end = y;\n while (\n end + 1 < bbox.y + bbox.h &&\n rgba[((end + 1) * canvasW + x) * 4 + 3] >= ALPHA_OPAQUE &&\n lum((end + 1) * canvasW + x) < dark\n ) {\n end++;\n }\n row = end;\n break;\n }\n if (row >= 0) found = true;\n out.push(row);\n }\n return found ? out : undefined;\n}\n\n/**\n * Measures a layer set one decoded layer at a time, so a host holds one\n * full-canvas RGBA buffer at once, however many layers the set has. Call\n * `finish` once, after the last `add`: it hands back its own `layers` array,\n * which a later `add` would change.\n */\nexport interface LayerSetMeasurer {\n /**\n * Measure one layer while its `rgba` is in memory, keeping no reference to\n * it: only the set's opaque union, this layer's per-row opaque extent and\n * the `LayerInput` it returns outlive the call, so the host may drop `rgba`\n * as soon as it returns. Returns the layer's `LayerInput` — its crop\n * box, the face's `rowHalfWidths`, the face's and hair layers' `rowRuns`, the nose's\n * `denseCore` unless that is a speck of its crop (`isSpeckCore`) — or\n * `null` for an empty layer, one with no pixel at or above\n * `ALPHA_BBOX_THRESHOLD`, which it records nothing for: the host reports\n * that with its own error. Throws, naming the file, when\n * `rgba` is not `width × height × 4` long; checking the decoded dimensions\n * is the host's job.\n */\n add(layer: RgbaLayer): LayerInput | null;\n /** The set's measurement, over every layer `add` recorded. The set must be\n * one `parseLayerRoles` accepted; otherwise this may throw, or measure a\n * partial set the generator then refuses. */\n finish(): LayerSetMeasurement;\n}\n\nexport interface LayerSetMeasurement {\n /** Every recorded layer's `LayerInput`, in `add` order. */\n layers: LayerInput[];\n /** The head's half-width at the eye row, canvas px: half the opaque\n * (alpha ≥ ALPHA_OPAQUE) union's span over ±HEAD_BAND rows about the row\n * of the iris centres, or of the eye centres without irises. Absent when\n * the union has no span there — a layer set painted translucent below that\n * threshold. */\n headHalfWidth?: number;\n /** Whether `headHalfWidth` is wider than the face plate, and so applied;\n * the face plate stands in for it otherwise, as the generator's own\n * fallback. */\n headHalfWidthApplied: boolean;\n /**\n * Ready to go into `generateIkiFromLayerSet`'s options, each key present\n * only when measured: `turnTargets.headHalfWidth` when it is applied (merge\n * the caller's own targets under it), `headEdges` — every layer's own\n * opaque extent in the same eye-row band, per side, in model x — with it,\n * and `strandEdges` whenever the set has `hair_front`, `iris_L` and `iris_R`\n * and a side measures one (`IrisStrand`).\n */\n turnOptions: {\n turnTargets?: { headHalfWidth: number };\n headEdges?: {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n };\n strandEdges?: { left?: IrisStrand; right?: IrisStrand };\n };\n}\n\n/**\n * The row the head's width is measured at: the mean of the iris centres, or of\n * the eye centres when the layer set has no irises. `@ikijs/mcp`'s\n * `measure_turn_reference` picks the same row off a render — it finds the\n * irises themselves — so the head it spans there is the head spanned here. Not\n * the generator's own eye row (`HeadFrame.eyeY` in `auto-rig/head.ts`, the eye\n * landmarks' mean model y, unrounded): this\n * is the canvas row of the crop centres, rounded, and one in place of the other\n * would move the measured head.\n */\nfunction eyeBandRowOf(layers: LayerInput[]): number {\n const centreY = (role: string): number | undefined => {\n const layer = layers.find((l) => l.role === role);\n return layer && layer.bbox.y + layer.bbox.h / 2;\n };\n const pairRow = (left: string, right: string): number | undefined => {\n const a = centreY(left);\n const b = centreY(right);\n return a === undefined || b === undefined ? undefined : (a + b) / 2;\n };\n const row = pairRow(\"iris_L\", \"iris_R\") ?? pairRow(\"eye_L\", \"eye_R\");\n if (row === undefined) {\n // eye_L/eye_R are required roles: a set without them is one\n // parseLayerRoles refuses, which `finish` requires the host to have run.\n throw new Error(\"auto-rig: no eye pair to measure the head width at\");\n }\n return Math.round(row);\n}\n\n/**\n * `foregroundSpan`, but over one layer's own already-reduced per-row\n * left/right (see `rowSpansByRole` in `createLayerSetMeasurer`) instead of a\n * pixel mask — the same row-band reduction, without re-scanning pixels.\n */\nfunction foregroundSpanOfRows(\n rowLeft: Int32Array,\n rowRight: Int32Array,\n rowLo: number,\n rowHi: number,\n): { left: number; right: number } {\n let left = Infinity;\n let right = -Infinity;\n for (\n let y = Math.max(0, rowLo);\n y <= Math.min(rowLeft.length - 1, rowHi);\n y++\n ) {\n if (rowLeft[y] < left) left = rowLeft[y];\n if (rowRight[y] > right) right = rowRight[y];\n }\n return { left, right };\n}\n\n/** The face plate's half-width, derived the way generateIkiFromLayerSet derives\n * it — off the `face` layer's cropped width — so the two agree on which head\n * is the wider one. */\nfunction facePlateHalfOf(layers: LayerInput[]): number {\n const face = layers.find((l) => l.role === \"face\");\n if (face === undefined) {\n // `face` is a required role: a set without it is one parseLayerRoles\n // refuses, which `finish` requires the host to have run.\n throw new Error(\"auto-rig: no face layer to measure the plate against\");\n }\n return face.cropW / 2;\n}\n\n/**\n * The narrowest `hair_front` run, as a fraction of an iris's painted width on\n * its centre row, that the strand scan takes as a strand. A run narrower than\n * this (strictly `<`; one exactly this wide is a strand) is hair detail and\n * counts as clear: the far iris may cross it on the turn, as intended. The\n * hero's row shows why: 5 px inside its 67 px side strand lies an 8 px wisp\n * the iris is painted 2 px under, and bounding the iris against that wisp cut\n * the −30 eye shift from ≈ 0.18 to 0.14.\n */\nconst STRAND_MIN_RUN_FRACTION = 0.5;\n\n/**\n * Start measuring a layer set on a `canvas`-sized canvas: the pass a host runs\n * between decoding its layers and `generateIkiFromLayerSet`. `add` each\n * decoded layer, then `finish`.\n *\n * Throws before allocating anything when `canvas.width` or `canvas.height` is\n * not a positive safe integer, or `width × height × 4` is not a safe integer.\n * How large a canvas to accept at all is each host's own limit.\n */\nexport function createLayerSetMeasurer(canvas: {\n width: number;\n height: number;\n}): LayerSetMeasurer {\n for (const field of [\"width\", \"height\"] as const) {\n const value = canvas[field];\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(\n `auto-rig: createLayerSetMeasurer: canvas.${field} must be a positive safe integer, got ${value}`,\n );\n }\n }\n const { width: canvasW, height: canvasH } = canvas;\n const rgbaLength = canvasW * canvasH * 4;\n if (!Number.isSafeInteger(rgbaLength)) {\n throw new Error(\n `auto-rig: createLayerSetMeasurer: canvas ${canvasW}x${canvasH} is too large: width × height × 4 = ${rgbaLength} is not a safe integer`,\n );\n }\n\n // Union of EVERY layer's opaque pixels — the silhouette the head half-width\n // is measured off in `finish`. Every layer folds in, so a body or an\n // accessory crossing the eye band widens the span; that is deliberate,\n // because a rest render of the finished rig shows the same union and\n // measures the same.\n const opaque = new Uint8Array(canvasW * canvasH);\n const layerInputs: LayerInput[] = [];\n // Per layer, per row: its OWN leftmost/rightmost opaque column (canvasW /\n // -1 where it has none that row) — recorded in the SAME pass as the union\n // fold, while the layer's decoded pixels are still live, rather than a\n // second decode pass. Read in `finish` once the eye row is known: each\n // layer's own extent in the eye-row band (`headEdges`), which the generator\n // lands through that layer's own deformation, and each iris's on its centre\n // row (`strandEdges`).\n const rowSpansByRole: {\n role: string;\n rowLeft: Int32Array;\n rowRight: Int32Array;\n }[] = [];\n\n function add({ role, fileName, rgba }: RgbaLayer): LayerInput | null {\n if (rgba.length !== rgbaLength) {\n throw new Error(\n `auto-rig: layer \"${fileName}\": rgba length ${rgba.length} is not ${canvasW}x${canvasH}x4 = ${rgbaLength}`,\n );\n }\n const bbox = detectAlphaBbox(rgba, canvasW, canvasH);\n if (bbox === null) return null;\n // Fold this layer into the silhouette AND record its own per-row extent\n // while its pixels are still here — one pass over the same pixels.\n const rowLeft = new Int32Array(canvasH).fill(canvasW);\n const rowRight = new Int32Array(canvasH).fill(-1);\n const rowRuns: number[][] | undefined =\n role === \"face\" || role === \"hair_front\" || role === \"hair_back\"\n ? []\n : undefined;\n for (let y = 0; y < canvasH; y++) {\n // Every opaque pixel lies inside the crop, so only its rows hold runs.\n let runs: number[] | undefined;\n if (rowRuns !== undefined && y >= bbox.y && y < bbox.y + bbox.h) {\n runs = [];\n rowRuns.push(runs);\n }\n let inRun = false;\n for (let x = 0; x < canvasW; x++) {\n const p = y * canvasW + x;\n const on = rgba[p * 4 + 3] >= ALPHA_OPAQUE;\n if (runs !== undefined && on !== inRun) {\n runs.push(x);\n inRun = on;\n }\n if (!on) continue;\n opaque[p] = 1;\n if (x < rowLeft[y]) rowLeft[y] = x;\n if (x > rowRight[y]) rowRight[y] = x;\n }\n if (runs !== undefined && inRun) runs.push(canvasW);\n }\n rowSpansByRole.push({ role, rowLeft, rowRight });\n const layer: LayerInput = {\n role,\n fileName,\n canvasW,\n canvasH,\n bbox,\n cropW: bbox.w,\n cropH: bbox.h,\n };\n if (rowRuns !== undefined) layer.rowRuns = rowRuns;\n if (role === \"face\") {\n // The plate's painted half-width on each of its crop rows — the same\n // alpha rule and halving as the head's own span, row by row (0 for a\n // row with no opaque pixel; a single opaque pixel IS a half-px row\n // here, where the head-span reads below treat a one-column band as\n // no span) — which give the plate's outline, the neck's plateau and\n // the ears' steps. The bbox admits alpha down to 8 while the span counts\n // alpha >= 128 only, so a row's span sits inside the crop and its\n // half never exceeds cropW / 2, the generator's bound.\n const rowHalfWidths: number[] = [];\n for (let y = bbox.y; y < bbox.y + bbox.h; y++) {\n rowHalfWidths.push(\n rowRight[y] >= rowLeft[y]\n ? headHalfOf({ left: rowLeft[y], right: rowRight[y] })\n : 0,\n );\n }\n layer.rowHalfWidths = rowHalfWidths;\n const jawRows = jawRowsOf(rgba, canvasW, bbox, rowLeft, rowRight);\n if (jawRows !== undefined) layer.jawRows = jawRows;\n } else if (role === \"nose\") {\n // The drawing inside a soft nose's feather, canvas px like `bbox` —\n // `rgba` is this layer's full-canvas buffer, so the core comes out in\n // the same coordinates as `bbox` and every other measurement here.\n // `null` (wholly translucent) or a speck of the crop (a lone nostril\n // mark, which `@ikijs/mcp`'s measure_layers flags on this same layer)\n // leaves `denseCore` unset, the generator falling back to the crop.\n const core = denseCoreOf(rgba, canvasW, canvasH);\n if (core !== null && !isSpeckCore(core, bbox)) layer.denseCore = core;\n }\n layerInputs.push(layer);\n return layer;\n }\n\n function finish(): LayerSetMeasurement {\n // The head's own half-width at the eye row, in canvas px, taken off the\n // layers' opaque union the way measure_turn_reference takes it off a render\n // (alpha rule, same row band, same halving) — so a rest render of this rig\n // measures the same span back. It is what the turn's shift targets are\n // fractions of; the generator's own fallback is the face plate, which is\n // narrower than the head the hair draws, and every shift then lands short.\n const eyeRow = eyeBandRowOf(layerInputs);\n const span = foregroundSpan(\n opaque,\n canvasW,\n canvasH,\n eyeRow - HEAD_BAND,\n eyeRow + HEAD_BAND,\n );\n // A layer set painted below the ALPHA_OPAQUE threshold (translucent art —\n // still above detectAlphaBbox's own, much lower, floor) has no confident\n // span here. That is not the same as having no head: fall back to the face\n // plate, same as a span that measures narrower than it below, rather than\n // refuse the whole rig over a union that is merely non-opaque.\n const headHalfWidth = span.right > span.left ? headHalfOf(span) : undefined;\n // ...but only when it IS wider than the plate. A hairless set, one whose\n // face plate is what the eye row is widest at, or one with no confident\n // span at all, measures a head the generator refuses (the silhouette\n // hold's zone would sit inside the plate) — and the right answer there is\n // the plate it falls back to, not no rig at all.\n const headHalfWidthApplied =\n headHalfWidth !== undefined &&\n headHalfWidth > facePlateHalfOf(layerInputs);\n\n // Every layer's own opaque extent in the same band — a companion to\n // headHalfWidth, only meaningful once it is actually applied (the\n // fallback path has no measured edge to report at all). The generator\n // lands each candidate through its OWN deformation and takes the\n // outermost LANDING, not just the outermost REST pixel, since which part\n // ends up furthest out after the turn can differ from which one drew\n // furthest out at rest. Model x (canvas x minus half the canvas width),\n // matching the generator's own placement of a layer (`boxOfLayer`).\n let headEdges:\n | {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n }\n | undefined;\n if (headHalfWidthApplied) {\n const bandLo = eyeRow - HEAD_BAND;\n const bandHi = eyeRow + HEAD_BAND;\n const left: { role: string; x: number }[] = [];\n const right: { role: string; x: number }[] = [];\n for (const { role, rowLeft, rowRight } of rowSpansByRole) {\n const own = foregroundSpanOfRows(rowLeft, rowRight, bandLo, bandHi);\n if (own.right <= own.left) continue; // no opaque pixel here at all\n left.push({ role, x: own.left - canvasW / 2 });\n right.push({ role, x: own.right - canvasW / 2 });\n }\n headEdges = { left, right };\n }\n\n // Each iris against the bangs' run it would slide under on the turn, on\n // ONE row — the one holding the iris's centre — under ONE rule (alpha >=\n // ALPHA_OPAQUE), a bangs run narrower than STRAND_MIN_RUN_FRACTION of that\n // iris's row width counting as clear. The iris's alpha-bbox (alpha >= 8, grown by a pixel) only\n // gives that row and where to start scanning, never an edge: every number\n // is the pixel boundary facing the neighbouring clear pixel, less half the\n // canvas, so each is the painted edge the way the generator's crop edges\n // (`boxOfLayer`) are. The scan decides with the very crop centres the\n // generator validates these edges against, so what it measures is always\n // accepted, on either side. A side's iris is whichever sits on that side,\n // the two paired by x rather than by role name. Measured whether or not\n // headHalfWidth is applied: the bound it feeds is the far iris against its\n // own strand, not the head's width.\n let strandEdges: { left?: IrisStrand; right?: IrisStrand } | undefined;\n const irisLayers = layerInputs\n .filter((l) => l.role === \"iris_L\" || l.role === \"iris_R\")\n .sort((a, b) => a.bbox.x + a.bbox.w / 2 - (b.bbox.x + b.bbox.w / 2));\n const hairFront = layerInputs.find((l) => l.role === \"hair_front\");\n const hairRuns = hairFront?.rowRuns;\n if (\n hairFront !== undefined &&\n hairRuns !== undefined &&\n irisLayers.length === 2\n ) {\n const hairTop = hairFront.bbox.y;\n const half = canvasW / 2;\n const strandOn = (\n iris: LayerInput,\n other: LayerInput,\n side: -1 | 1,\n ): IrisStrand | undefined => {\n const r = Math.floor(iris.bbox.y + iris.bbox.h / 2);\n // The iris's crop centre, canvas x (a pixel boundary for an even\n // width, a pixel's middle for an odd one), and the other's in model\n // x — the generator's placement of each (`boxOfLayer`).\n const centre = iris.bbox.x + iris.bbox.w / 2;\n const otherX = other.bbox.x + other.bbox.w / 2 - half;\n // The pixel just on THIS side of that centre: a run covering it\n // reaches outward past the centre, so its outer end is strictly\n // outward of it on either side, which a pixel chosen by one rounding\n // for both sides would not give.\n const c = side < 0 ? Math.ceil(centre) - 1 : Math.floor(centre);\n const span = rowSpansByRole.find((s) => s.role === iris.role)!;\n // An iris with no opaque pixel on its own centre row has no edge.\n if (span.rowRight[r] < span.rowLeft[r]) return undefined;\n // The row's strand pixels: hair_front's opaque runs on it, less every\n // run narrower than STRAND_MIN_RUN_FRACTION of this iris's painted\n // width there, which the whole scan below reads as clear. Runs are\n // judged whole, so the result is the same from either side.\n const minRun =\n STRAND_MIN_RUN_FRACTION * (span.rowRight[r] + 1 - span.rowLeft[r]);\n const strand = new Uint8Array(canvasW);\n // A row outside the bangs' crop has no opaque pixel of theirs.\n const runs =\n r >= hairTop && r < hairTop + hairRuns.length\n ? hairRuns[r - hairTop]\n : [];\n for (let k = 0; k < runs.length; k += 2) {\n if (runs[k + 1] - runs[k] >= minRun) {\n strand.fill(1, runs[k], runs[k + 1]);\n }\n }\n const strandAt = (x: number) =>\n x >= 0 && x < canvasW && strand[x] === 1;\n // The boundary between pixel x and its neighbour one step outward.\n const outerBoundary = (x: number) => (side < 0 ? x : x + 1) - half;\n let x = c;\n let runFace: number | null;\n if (!strandAt(c)) {\n // A clear centre (or one under a thin run only): the first strand\n // pixel outward starts the run, and its face-side boundary is\n // runFace.\n while (x >= 0 && x < canvasW && !strandAt(x)) x += side;\n if (x < 0 || x >= canvasW) return undefined; // no run outward\n runFace = outerBoundary(x - side);\n } else {\n // A covered centre: the run's face-side end is where it clears on\n // the face side — when that is strictly on this side of the other\n // iris's centre. A run still opaque there is a fringe spanning the\n // face, which has no face-side end on this side.\n let f = c - side;\n while (strandAt(f)) f -= side;\n const face = outerBoundary(f);\n runFace = side * (face - otherX) > 0 ? face : null;\n }\n // Outward to the run's outer end: its last opaque pixel's boundary\n // with the first clear one after it, or with the crop's edge.\n while (strandAt(x)) x += side;\n return {\n y: canvasH / 2 - (r + 0.5),\n irisOuter: (side < 0 ? span.rowLeft[r] : span.rowRight[r] + 1) - half,\n irisInner: (side < 0 ? span.rowRight[r] + 1 : span.rowLeft[r]) - half,\n runOuter: outerBoundary(x - side),\n runFace,\n };\n };\n const [low, high] = irisLayers;\n const left = strandOn(low, high, -1);\n const right = strandOn(high, low, 1);\n if (left !== undefined || right !== undefined) {\n strandEdges = {\n ...(left === undefined ? {} : { left }),\n ...(right === undefined ? {} : { right }),\n };\n }\n }\n\n return {\n layers: layerInputs,\n ...(headHalfWidth === undefined ? {} : { headHalfWidth }),\n headHalfWidthApplied,\n turnOptions: {\n ...(headHalfWidthApplied ? { turnTargets: { headHalfWidth } } : {}),\n ...(headEdges === undefined ? {} : { headEdges }),\n ...(strandEdges === undefined ? {} : { strandEdges }),\n },\n };\n }\n\n return { add, finish };\n}\n","import type { IkiTransformChannel } from \"@ikijs/format\";\n\n/**\n * Pure, binding-value logic for computing an endpoint (rest-to-posed delta or\n * ratio) when capturing a transform channel binding. No DOM, no @ikijs/engine —\n * the single home of the additive-vs-multiplicative rule, reused by both the\n * part and deformer capture paths.\n *\n * Additive channels (translateX, translateY, rotate, scaleX, scaleY) return the\n * delta: `posedValue - restValue`. The binding will multiply that delta across\n * the driven range.\n *\n * Opacity is multiplicative: returns the ratio `posedValue / restValue`. The\n * binding will multiply by that ratio across the driven range. When `restValue`\n * is 0 (a degenerate case: base opacity cannot be represented multiplicatively\n * since 0 * x ≡ 0), this returns 0 as a documented fallback — it does NOT\n * recover `posedValue` and is NOT unit-tested as an identity. The store layer\n * additionally skips an opacity capture when rest opacity is 0, surfacing an\n * editError.\n *\n * Deformer channels never include opacity (they use `IkiMatrixChannel`), so the\n * opacity branch is reached only for parts.\n *\n * Finiteness of the captured value is NOT validated here; the store's\n * `captureEndpoint` finite-value guard is the appropriate layer for that check.\n */\nexport function captureBindingEndpoint(\n channel: IkiTransformChannel,\n restValue: number,\n posedValue: number,\n): number {\n if (channel === \"opacity\") {\n return restValue === 0 ? 0 : posedValue / restValue;\n }\n return posedValue - restValue;\n}\n","import type { IkiUvRect } from \"@ikijs/format\";\n\nexport const ATLAS_PADDING = 2;\nexport const UV_INSET_PX = 0.5;\n\n/** Intrinsic pixel size of one decoded image; id is an editor-only stable key. */\nexport interface AtlasSource {\n id: string;\n width: number;\n height: number;\n}\n\n/** Sub-image pixel rect within the page, top-left origin, EXCLUDING the gutter. */\nexport interface AtlasPlacement {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface AtlasLayout {\n pageWidth: number;\n pageHeight: number;\n placements: AtlasPlacement[];\n padding: number;\n}\n\n/**\n * Deterministic shelf/row packer. Sources are sorted by id for stability so\n * identical inputs always produce an identical layout.\n *\n * Padding is one-sided: each placement reserves `padding` px on its RIGHT and\n * BOTTOM only. Page left/top edges need no gutter.\n *\n * pageWidth/pageHeight = tight bound (max x+width+padding, max y+height+padding).\n * Empty sources → { pageWidth: 0, pageHeight: 0, placements: [], padding }.\n * Throws a plain Error naming the offending source id on a non-finite or <= 0 dimension.\n */\nexport function packAtlas(\n sources: AtlasSource[],\n padding = ATLAS_PADDING,\n): AtlasLayout {\n for (const src of sources) {\n if (!isFinite(src.width) || src.width <= 0) {\n throw new Error(\n `packAtlas: source \"${src.id}\" has invalid width ${src.width}`,\n );\n }\n if (!isFinite(src.height) || src.height <= 0) {\n throw new Error(\n `packAtlas: source \"${src.id}\" has invalid height ${src.height}`,\n );\n }\n }\n\n if (sources.length === 0) {\n return { pageWidth: 0, pageHeight: 0, placements: [], padding };\n }\n\n // Stable sort by id so identical inputs always produce the same layout.\n const sorted = sources\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n\n // Target page width: ceil(sqrt(total padded area)), raised to a sane minimum.\n const totalArea = sorted.reduce(\n (sum, s) => sum + (s.width + padding) * (s.height + padding),\n 0,\n );\n const targetWidth = Math.max(\n Math.ceil(Math.sqrt(totalArea)),\n // Ensure at least the widest single source fits.\n Math.max(...sorted.map((s) => s.width + padding)),\n );\n\n const placements: AtlasPlacement[] = [];\n let shelfX = 0;\n let shelfY = 0;\n let shelfHeight = 0; // tallest padded item in the current row\n\n for (const src of sorted) {\n const paddedW = src.width + padding;\n const paddedH = src.height + padding;\n\n // Wrap to next row when the item doesn't fit on the current shelf.\n if (shelfX > 0 && shelfX + paddedW > targetWidth) {\n shelfY += shelfHeight;\n shelfX = 0;\n shelfHeight = 0;\n }\n\n placements.push({\n id: src.id,\n x: shelfX,\n y: shelfY,\n width: src.width,\n height: src.height,\n });\n\n shelfX += paddedW;\n if (paddedH > shelfHeight) shelfHeight = paddedH;\n }\n\n // Tight page bounds: max right/bottom padded edge across all placements.\n let pageWidth = 0;\n let pageHeight = 0;\n for (const p of placements) {\n const right = p.x + p.width + padding;\n const bottom = p.y + p.height + padding;\n if (right > pageWidth) pageWidth = right;\n if (bottom > pageHeight) pageHeight = bottom;\n }\n\n return { pageWidth, pageHeight, placements, padding };\n}\n\n/**\n * Convert a pixel placement into a UV rect, inset by `insetPx` on all four\n * edges and clamped to [0, 1] so the validator's bounds check always passes.\n */\nexport function uvRectFor(\n placement: AtlasPlacement,\n page: { width: number; height: number },\n insetPx = UV_INSET_PX,\n): IkiUvRect {\n const px = placement.x + insetPx;\n const py = placement.y + insetPx;\n const pw = placement.width - insetPx * 2;\n const ph = placement.height - insetPx * 2;\n\n const x = Math.max(0, px / page.width);\n const y = Math.max(0, py / page.height);\n const width = Math.min(1 - x, Math.max(0, pw / page.width));\n const height = Math.min(1 - y, Math.max(0, ph / page.height));\n\n return { x, y, width, height };\n}\n","import type {\n IkiMatrixDeformer,\n IkiMesh,\n IkiModel,\n IkiPart,\n IkiWarpDeformer,\n} from \"@ikijs/format\";\n\n/**\n * Pure, DOM-free factory helpers for creating new model objects from scratch.\n * Kept separate from `commands.ts` (which is edit-only) so that the \"add item\"\n * use-case has a dedicated, testable home with no mutation concerns.\n *\n * All factories accept the live model so they can derive a collision-free id and\n * a sensible draw-order / grid span without hard-coding sample assumptions.\n */\n\n/**\n * Return the first collision-free id in the shared part+deformer namespace.\n * Parts and deformers share a flat id namespace (validate.ts:692-706), so we\n * scan both arrays. Returns `base` if unused; otherwise tries `${base}_2`,\n * `${base}_3`, … until a free slot is found.\n *\n * Parameters are a separate namespace and are NOT included in the scan.\n */\nfunction generateUniqueId(model: IkiModel, base: string): string {\n const used = new Set<string>();\n for (const p of model.parts) {\n used.add(p.id);\n }\n for (const d of model.deformers ?? []) {\n used.add(d.id);\n }\n\n if (!used.has(base)) return base;\n\n let n = 2;\n while (true) {\n const candidate = `${base}_${n}`;\n if (!used.has(candidate)) return candidate;\n n++;\n }\n}\n\n/**\n * Generate the flat `[x0,y0, x1,y1, …]` rest-grid control points for a\n * regular axis-aligned lattice with `(cols+1)*(rows+1)` points, row-major.\n *\n * Row 0 is the TOP (y = maxY); y strictly decreases with row index.\n * Column 0 is left (x = minX); x strictly increases with column index.\n * This ordering satisfies the `IkiWarpGrid` rest-grid invariant\n * (packages/format/src/types.ts:178-196) required by the validator and\n * the engine's grid-sampling code.\n */\nfunction generateRegularGridPoints(\n cols: number,\n rows: number,\n minX: number,\n maxX: number,\n minY: number,\n maxY: number,\n): number[] {\n const pts: number[] = [];\n for (let row = 0; row <= rows; row++) {\n const t = row / rows;\n const y = maxY - t * (maxY - minY); // maxY at row 0, minY at row `rows`\n for (let col = 0; col <= cols; col++) {\n const s = col / cols;\n const x = minX + s * (maxX - minX); // minX at col 0, maxX at col `cols`\n pts.push(x, y);\n }\n }\n return pts;\n}\n\n/**\n * Create a minimal valid part with a collision-free id and a paint order one\n * above the current top-most part so it is immediately visible in the viewport.\n * Uses a distinct non-white blue tint so it is distinguishable from the canvas\n * background without requiring a texture.\n *\n * No optional keys (`texture`, `mesh`, `deformer`, `bindings`, `warps`) are set\n * — the format treats all of them as absent by default.\n */\nexport function createDefaultPart(model: IkiModel): IkiPart {\n const order = model.parts.length\n ? Math.max(...model.parts.map((p) => p.order)) + 1\n : 0;\n\n return {\n id: generateUniqueId(model, \"part\"),\n color: [0.45, 0.6, 0.85, 1],\n width: 150,\n height: 150,\n transform: { x: 0, y: 0 },\n order,\n };\n}\n\n/**\n * Create a minimal valid matrix deformer rooted at the canvas origin.\n * `kind` is omitted because the format treats its absence as \"matrix\" (the\n * default), keeping the serialised model compact.\n */\nexport function createDefaultMatrixDeformer(\n model: IkiModel,\n): IkiMatrixDeformer {\n return {\n id: generateUniqueId(model, \"deformer\"),\n pivot: { x: 0, y: 0 },\n };\n}\n\n/**\n * Create a regular grid mesh in part LOCAL space (±0.5 unit frame).\n *\n * Vertices span x ∈ [-0.5, 0.5] and y ∈ [-0.5, 0.5] (+y up, engine convention).\n * Row 0 is the TOP of the grid (y = +0.5); row index increases downward.\n * UVs are unit-square base coordinates: u = col/cols (0..1 left→right),\n * v = row/rows (0..1 top→bottom). The top row maps to v=0 because v and y\n * run in opposite directions — keeps textures upright without a post-flip.\n * The UV-to-texture remap (atlas rect) is applied later in SetPartMesh, not here.\n *\n * Index winding per cell: [BL, BR, TL] then [TL, BR, TR], matching the engine's\n * implicit-quad convention (see examples/editor/src/mesh-generator.ts).\n *\n * Bounds are validated BEFORE any array allocation because this factory runs\n * before SetPartMesh's parseIkiModel — an unbounded count would freeze the\n * editor before the format-level 65536 limit is ever reached.\n */\nexport function createGridMesh(cols: number, rows: number): IkiMesh {\n // Guard: cols/rows must be integers ≥1 and the vertex count must fit within\n // the format limit of 65536 vertices (packages/format/src/validate.ts parseMesh).\n if (\n !Number.isInteger(cols) ||\n cols < 1 ||\n !Number.isInteger(rows) ||\n rows < 1 ||\n (cols + 1) * (rows + 1) > 65536\n ) {\n throw new Error(\n \"createGridMesh: cols and rows must be integers >= 1 with (cols+1)*(rows+1) <= 65536\",\n );\n }\n\n const colVerts = cols + 1;\n const rowVerts = rows + 1;\n\n const vertices: number[] = [];\n const uvs: number[] = [];\n\n // Row 0 is TOP (y = +0.5). Row `rows` is BOTTOM (y = -0.5).\n // Column 0 is left (x = -0.5). Column `cols` is right (x = +0.5).\n for (let row = 0; row < rowVerts; row++) {\n const t = row / rows;\n const y = 0.5 - t; // +0.5 at row 0, -0.5 at row `rows`\n const v = t; // 0 at top row, 1 at bottom row\n\n for (let col = 0; col < colVerts; col++) {\n const s = col / cols;\n const x = -0.5 + s; // -0.5 at col 0, +0.5 at col `cols`\n const u = s; // 0 at left col, 1 at right col\n\n vertices.push(x, y);\n uvs.push(u, v);\n }\n }\n\n // Two triangles per cell: [BL, BR, TL] then [TL, BR, TR].\n const indices: number[] = [];\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const tl = row * colVerts + col;\n const tr = row * colVerts + col + 1;\n const bl = (row + 1) * colVerts + col;\n const br = (row + 1) * colVerts + col + 1;\n\n indices.push(bl, br, tl);\n indices.push(tl, br, tr);\n }\n }\n\n return { vertices, uvs, indices };\n}\n\n/**\n * Create a 4×4-cell warp deformer whose rest grid spans a quarter of the\n * canvas in each direction (`±canvas.width/4` × `±canvas.height/4`). For the\n * 1000-unit sample canvas this gives x,y ∈ [−250, 250], which is large enough\n * to cover a typical face part without spilling to the edge.\n *\n * `warps` is omitted — the format treats its absence as \"rest grid only\", so\n * the deformer is immediately usable without authored keyforms.\n * `parent` is omitted — the deformer is placed at root; the caller may\n * reparent it via `SetDeformerParent` after creation.\n */\nexport function createDefaultWarpDeformer(model: IkiModel): IkiWarpDeformer {\n const hx = model.canvas.width / 4;\n const hy = model.canvas.height / 4;\n\n return {\n kind: \"warp\",\n id: generateUniqueId(model, \"warp\"),\n grid: {\n cols: 4,\n rows: 4,\n points: generateRegularGridPoints(4, 4, -hx, hx, -hy, hy),\n },\n };\n}\n","/**\n * How far each region of a head moves at the extremes of each head\n * parameter. The rules are a 2D rig's usual ones. A turn is parallax, not a\n * reshaped face: the face plate translates, the features in front of it lead\n * it by their depth (the nose most), the chin leads it too, the front hair\n * rides the face, the back hair drifts a little the other way, and the neck\n * and the torso stay where they are. A nod is the same parallax vertically;\n * a roll turns the head about the chin. Every curve is linear in its\n * parameter, so one keyform per extreme carries it exactly.\n *\n * The magnitudes are our own values, `PROFILE_VALUES`, picked by eye on our\n * own characters (`packages/editor/AUTO-RIG.md`); what the rig reads —\n * `TURN`, `NOD`, `ROLL_DEG` and `AMPLITUDE` — is derived from them. Lengths\n * are in the head unit `hh`, the eye row → chin tip at rest.\n */\n\n/** The values the profile is derived from, each at its parameter's extreme\n * (±30 for the head angles). */\nexport interface ProfileValues {\n /** AngleX: the face plate translates this far, hh. */\n slide: number;\n /** AngleX: a feature on the face — an eye, a brow, the mouth, the chin\n * tip — leads the plate by this, hh. */\n lead: number;\n /** AngleX: the nose leads the plate this many times `lead`. */\n noseDepth: number;\n /** AngleX: the front hair rides the face at this share of its slide. */\n hairFollow: number;\n /** AngleX: the far eye and the far ear narrow to 1 − fore of their width,\n * the near eye widens to 1 + fore / 2; each eye's and brow's lead scales\n * with its eye's width. */\n fore: number;\n /** The back hair takes this share of the plate's motion: against it on the\n * turn, with it on the nod. */\n backShare: number;\n /** AngleX: the far ear's outer edge moves this share of the plate's slide\n * (the near ear rides the head). */\n earFar: number;\n /** AngleY −30 (looking down): the plate's top drops this far, hh. */\n nodDown: number;\n /** AngleY +30 (looking up): the plate rises this far, whole, hh. */\n nodUp: number;\n /** AngleY: a feature on the face leads the plate's nod at mid-face by this\n * either way, hh; the nose `noseDepth` times it. */\n nodLead: number;\n /** AngleY −30: the chin drops this share of the plate's top. */\n chinShare: number;\n /** AngleZ ±30 rolls the head this many degrees about the chin. */\n rollDeg: number;\n /** The iris travels this many iris widths sideways, half as far up and\n * down. */\n gaze: number;\n /** How far the upper lid comes down, over the eye's height. */\n blink: number;\n /** A single mouth drawing opens to this height over its rest width. */\n mouthOpen: number;\n /** The mouth widens to this much of its width open. */\n mouthWiden: number;\n /** A brow raises and lowers this far, hh. */\n brow: number;\n /** A breath lifts the shoulders this far, hh, and the head two thirds of\n * it. */\n breath: number;\n /** A hair tip travels this far at full sway (±20), hh. */\n sway: number;\n /** At Cheek 0 the blush shows at this opacity; at Cheek 1, as drawn. */\n blushRest: number;\n}\n\n/** The values: round numbers picked by eye on our own characters (Bob and\n * the long-haired one), each against its neighbours on a coarse grid in a\n * blind A/B judged by a fresh agent and by us (2026-10); `AUTO-RIG.md` has\n * the record. */\nexport const PROFILE_VALUES: ProfileValues = {\n slide: 0.12,\n lead: 0.1,\n noseDepth: 2,\n hairFollow: 1,\n fore: 0.2,\n backShare: 0.1,\n earFar: 0.5,\n nodDown: 0.18,\n nodUp: 0.1,\n nodLead: 0.06,\n chinShare: 0.75,\n rollDeg: 14,\n gaze: 0.2,\n blink: 0.6,\n mouthOpen: 0.8,\n mouthWiden: 1.2,\n brow: 0.15,\n breath: 0.03,\n sway: 0.08,\n blushRest: 0.4,\n};\n\n/** What the rig reads, derived from `v`. */\nexport function deriveProfile(v: ProfileValues) {\n const farLead = v.lead * (1 - v.fore / 2);\n const nearLead = v.lead * (1 + v.fore / 2);\n /** AngleX ±30, hh along the turn (\"far\" = the side the face turns toward). */\n const turn = {\n /** The face plate's translation. */\n face: v.slide,\n /** The chin tip's lead over the plate. */\n chinLead: v.lead,\n /** The plate's width at full turn: eye and cheek rows, then the jaw. The\n * plate translates; it does not narrow. */\n widthUpper: 1,\n widthJaw: 1,\n eyeFar: v.slide + farLead,\n eyeNear: v.slide + nearLead,\n /** Each eye's width at full turn, about its own centre. */\n eyeFarScale: 1 - v.fore,\n eyeNearScale: 1 + v.fore / 2,\n browFar: v.slide + farLead,\n browNear: v.slide + nearLead,\n nose: v.slide + v.noseDepth * v.lead,\n mouth: v.slide + v.lead,\n mouthWidth: 1,\n /** The mouth's far corner rises (its near end drops) by this much: it\n * stays level. */\n mouthTiltDeg: 0,\n /** The front hair (bangs and side locks) rides the face at this share of\n * its translation. */\n hairFollow: v.hairFollow,\n /** The head's outline at the eye row holds: where the front hair draws\n * it, its outer edge follows the face this much on a row where no back\n * hair paints behind that edge. Where back hair does, the edge rides\n * further, as far as that back hair stays behind it through the turn and\n * the nod, up to the face's follow there (`hairFollow`; over the far\n * eye's rows, as far as that eye's outer corner goes). On the cap (the\n * rows above the eyes) it follows less where the turn would otherwise\n * carry it further outside its back hair than the nod alone does. */\n outlineFollow: 0,\n /** The back hair's slight counter-motion. */\n hairBack: -v.backShare * v.slide,\n /** The ears lag the plate: the far one's outer edge moves this share of\n * its slide; the near one rides the head. */\n earFar: v.earFar,\n earNear: 1,\n /** The far ear's width at full turn, about its outer edge, where the head\n * leaves it room; less where it does not. */\n earFarScale: 1 - v.fore,\n };\n // The plate's nod halfway between its top and the chin, looking down.\n const mid = (v.nodDown * (1 + v.chinShare)) / 2;\n const feature = (depth: number) => ({\n up: -(v.nodUp + depth * v.nodLead),\n down: mid + depth * v.nodLead,\n });\n /** AngleY: screen displacement, hh, + = DOWN, at +30 (looking up) and −30\n * (looking down). */\n const nod = {\n faceTop: { up: -v.nodUp, down: v.nodDown },\n chin: { up: -v.nodUp, down: v.chinShare * v.nodDown },\n eye: feature(1),\n /** Eye height at the extreme, about the eye's centre: it holds. */\n eyeHeight: { up: 1, down: 1 },\n brow: feature(1),\n nose: feature(v.noseDepth),\n mouth: feature(1),\n hairFront: { up: -v.hairFollow * v.nodUp, down: v.hairFollow * v.nodDown },\n /** The front hair's cap top: half the plate's rise looking up; looking\n * down the plate's top, which the rig slides only as far as the back\n * hair covers the crown behind it. */\n hairFrontTop: { up: -v.nodUp / 2, down: v.nodDown },\n hairBack: { up: -v.backShare * v.nodUp, down: v.backShare * v.nodDown },\n };\n /** Everything else, at each parameter's extreme. */\n const amplitude = {\n /** Iris travel, in iris widths. */\n gazeX: v.gaze,\n gazeY: v.gaze / 2,\n /** How far the upper lid comes down, over the eye's height. */\n blink: v.blink,\n /** A single mouth drawing opens to this height over its rest width. */\n mouthOpenHeight: v.mouthOpen,\n /** The mouth widens this much open. */\n mouthOpenWidth: v.mouthWiden,\n /** Brow raise / lower, hh. */\n brow: v.brow,\n /** Breath lifts the shoulders and the head, hh. */\n breathBody: v.breath,\n breathHead: (v.breath * 2) / 3,\n /** Hair tip travel at full sway (±20), hh. */\n sway: v.sway,\n /** The blush's opacity at Cheek 0; at Cheek 1 it is as drawn. */\n blushRest: v.blushRest,\n /** The neck under the face reaches this far above the jaw, hh — what the\n * chin uncovers as it slides off it: half again the chin's full-turn\n * slide, to the next 0.05. */\n hiddenNeck: Math.ceil(30 * (v.slide + v.lead) - 1e-9) / 20,\n };\n return { TURN: turn, NOD: nod, ROLL_DEG: v.rollDeg, AMPLITUDE: amplitude };\n}\n\nexport const { TURN, NOD, ROLL_DEG, AMPLITUDE } = deriveProfile(PROFILE_VALUES);\n\n/**\n * Per-character tuning, starting from the profile. `turn`, `featureLead` and\n * `sway` multiply the profile (1 = the profile); `hairFollow`,\n * `outlineFollow` and `blink` replace its value. `AUTO-RIG.md` lists the\n * ranges that read well.\n */\nexport interface RigStyle {\n /** The whole turn — plate, features and hair. Ignored when a\n * `turnTargets.eyeShift` is given, which fits it instead. */\n turn?: number;\n /** How far the features lead the plate. */\n featureLead?: number;\n /** The front hair's share of the face's turn. */\n hairFollow?: number;\n /** Its outer edge's share, where the front hair draws the head's outline\n * and no back hair paints behind that edge (profile 0: the outline holds;\n * `hairFollow` rides it whole). Where back hair does, the edge rides\n * further, as far as that back hair stays behind it through the turn and\n * the nod, up to the front hair's follow there (`hairFollow`; over the\n * far eye's rows, as far as that eye's outer corner goes). On the cap\n * (the rows above the eyes) the edge follows less where the turn would\n * otherwise carry it further outside its back hair than the nod alone\n * does. */\n outlineFollow?: number;\n /** How far the upper lid comes down, over the eye's height. */\n blink?: number;\n /** Hair sway amplitude. */\n sway?: number;\n}\n\n/** Every knob `RigStyle` has: a caller's style names only these. */\nexport const STYLE_KNOBS: readonly (keyof RigStyle)[] = [\n \"turn\",\n \"featureLead\",\n \"hairFollow\",\n \"outlineFollow\",\n \"blink\",\n \"sway\",\n];\n\nexport interface ResolvedStyle {\n turn: number;\n featureLead: number;\n hairFollow: number;\n outlineFollow: number;\n blink: number;\n sway: number;\n}\n\n/** Style knobs resolved against the profile; `check` names a bad one. */\nexport function resolveStyle(\n style: RigStyle | undefined,\n check: (key: string, v: unknown, lo: number, hi: number) => number,\n): ResolvedStyle {\n const s = style ?? {};\n const get = (key: keyof RigStyle, def: number, lo: number, hi: number) =>\n s[key] === undefined ? def : check(`style.${key}`, s[key], lo, hi);\n return {\n turn: get(\"turn\", 1, 0, 3),\n featureLead: get(\"featureLead\", 1, 0, 3),\n hairFollow: get(\"hairFollow\", TURN.hairFollow, 0, 2),\n outlineFollow: get(\"outlineFollow\", TURN.outlineFollow, 0, 2),\n blink: get(\"blink\", AMPLITUDE.blink, 0.1, 1),\n sway: get(\"sway\", 1, 0, 5),\n };\n}\n","/**\n * The public shapes of the auto-rig: what a host hands `generateIkiFromLayerSet`\n * and what the turn solve reports back. Pixel measurement lives in\n * `layer-measure.ts`; everything here is already-decoded geometry.\n */\n\nimport { TURN, type RigStyle } from \"./profile\";\n\nconst round2 = (v: number) => Math.round(v * 100) / 100;\n\n/** One role layer, as a host measured it off its decoded pixels. */\nexport interface LayerInput {\n /** Canonical role (see `parseLayerRoles`); becomes the part id. */\n role: string;\n fileName: string;\n canvasW: number;\n canvasH: number;\n /** Alpha bounding box in canvas px (y down) — the crop the atlas holds. */\n bbox: { x: number; y: number; w: number; h: number };\n cropW: number;\n cropH: number;\n /** Face only: half the opaque span of each crop row, canvas px (0 = none). */\n rowHalfWidths?: number[];\n /** `face` / `hair_front` / `hair_back` only: per crop row, its opaque (alpha ≥ 128)\n * runs as a flat list of canvas columns `[start0, end0, start1, end1, …]`,\n * each end exclusive (`[]` for a row with none). The actual pixels, so a\n * gap in the hair is a gap here: the turn and the nod read off it where\n * back hair is painted behind the front hair, and the crown's turn reads the\n * face's so it never bares skin. */\n rowRuns?: number[][];\n /** Nose only: the tight box of its alpha ≥ 128 pixels, canvas px. */\n denseCore?: { x: number; y: number; w: number; h: number };\n /** Face only: per crop column, the canvas row of the last pixel of the\n * first dark stroke met going down from the plate's widest row (the jaw's\n * outline, across a neck), or −1 where the column leaves the paint first.\n * Where the head ends and the neck the body keeps begins. */\n jawRows?: number[];\n}\n\n/**\n * One side's iris against the `hair_front` run it would slide under on the\n * turn, on the row holding the iris centre. Model coordinates: x is canvas x\n * minus half the canvas width, y is half the canvas height minus canvas y.\n */\nexport interface IrisStrand {\n y: number;\n irisOuter: number;\n irisInner: number;\n runOuter: number;\n /** The run's face-side end; `null` for a fringe spanning the face. */\n runFace: number | null;\n}\n\n/**\n * Head-turn cues at ±30°, as `measure_turn_reference` reads them off a front\n * and a turned image. Shifts are fractions of the head half-width, taken as\n * magnitudes: that tool signs them by the reference's turn direction.\n */\nexport interface TurnTargets {\n eyeShift?: number;\n farEyeRatio?: number;\n silhouetteRatio?: number;\n noseShift?: number;\n mouthShift?: number;\n /** The head half-width the shifts are fractions of, canvas px. */\n headHalfWidth?: number;\n}\n\n/** A turn target this layer set cannot reach, or turn input that is malformed. */\nexport class TurnTargetError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TurnTargetError\";\n }\n}\n\n/**\n * The profile's own turn (`profile.ts`), in the cues' units — what a rig with\n * no `turnTargets` renders on a head whose silhouette at the eye row is back\n * hair about 1 hh (eye row → chin) wide. eyeShift: the eye pair's mean shift\n * at ±30 less the back hair's drift, over a 1 hh head half-width.\n * farEyeRatio: the far eye's width over the near one's. silhouetteRatio: the\n * silhouette holds its width.\n *\n * With no target given the rig renders the profile itself, whatever the cues\n * then read on its art (a head whose side locks draw its silhouette, and ride\n * the face, reads a smaller eyeShift); a given target is fitted.\n */\nexport const DEFAULT_TURN_TARGETS: Readonly<\n Required<Pick<TurnTargets, \"eyeShift\" | \"farEyeRatio\" | \"silhouetteRatio\">>\n> = Object.freeze({\n eyeShift: round2((TURN.eyeFar + TURN.eyeNear) / 2 - TURN.hairBack),\n farEyeRatio: round2(TURN.eyeFarScale / TURN.eyeNearScale),\n silhouetteRatio: 1,\n});\n\n/** How far each feature family stands in front of the plate, as the depth a\n * rotation would need to give its shift at ±30 (shift / sin 30°), in head\n * half-widths — the nose leads the mouth and the mouth the eyes. */\nexport interface TurnDepths {\n eye: number;\n nose: number;\n mouth: number;\n}\n\n/** How much of a far iris's painted row the bangs' run covers. */\nexport interface StrandOverlap {\n /** The turn stop (AngleX, degrees) where the coverage is largest. */\n deg: number;\n /** Covered width there, canvas px. */\n px: number;\n /** The same in head half-widths. */\n hh: number;\n /** Covered width at rest. */\n restPx: number;\n /** Whether the iris went no deeper under the run than it is painted.\n * Always `false` for a fringe spanning the face (`runFace: null`), which\n * has no side to keep the iris clear of. */\n held: boolean;\n}\n\nexport interface TurnSolveReport {\n /** The curvature the plate would need to put the eyes as far in front of\n * its edge as their lead over it does, as a radius, canvas px. */\n radius: number;\n /** The measured head half-width, canvas px, which the shift cues are\n * fractions of — on a set with none measured (hairless) the face crop's\n * half-width, while the cues are then fractions of the plate's painted\n * half-width at the eye row. */\n holdBase: number;\n depths: TurnDepths;\n /** What the rig renders at ±30° (mean of both directions). */\n achieved: { eyeShift: number; farEyeRatio: number; silhouetteRatio: number };\n /** Targets cut down to what this layer set can do. */\n clamped: (keyof TurnTargets)[];\n strandOverlap?: { left?: StrandOverlap; right?: StrandOverlap };\n}\n\nexport interface HeadEdges {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n}\n\nexport interface GenerateOptions {\n turnTargets?: TurnTargets;\n /** Per-character tuning from the profile's defaults (`profile.ts`). */\n style?: RigStyle;\n onTurnSolved?: (report: TurnSolveReport) => void;\n headEdges?: HeadEdges;\n strandEdges?: { left?: IrisStrand; right?: IrisStrand };\n}\n","/**\n * The roles a layer set may carry, in draw order (back to front), and the\n * file-name → role parse every host runs before measuring.\n */\n\n/** Which turn family a role rides: each family is baked on its own grid. */\nexport type Family =\n | \"face\"\n | \"eye_L\"\n | \"eye_R\"\n | \"brow_L\"\n | \"brow_R\"\n | \"nose\"\n | \"mouth\"\n | \"hair_front\"\n | \"hair_back\"\n | \"body\";\n\nexport interface RoleSpec {\n role: string;\n family: Family;\n required?: true;\n}\n\n/** Back to front. `@ikijs/mcp`'s composer draws in the same order. */\nexport const ROLE_TABLE: readonly RoleSpec[] = [\n { role: \"hair_back\", family: \"hair_back\" },\n { role: \"body\", family: \"body\" },\n { role: \"face\", family: \"face\", required: true },\n { role: \"blush_L\", family: \"face\" },\n { role: \"blush_R\", family: \"face\" },\n { role: \"nose\", family: \"nose\" },\n { role: \"mouth\", family: \"mouth\", required: true },\n { role: \"mouth_open\", family: \"mouth\" },\n { role: \"eye_L\", family: \"eye_L\", required: true },\n { role: \"eye_R\", family: \"eye_R\", required: true },\n { role: \"iris_L\", family: \"eye_L\" },\n { role: \"iris_R\", family: \"eye_R\" },\n { role: \"pupil_L\", family: \"eye_L\" },\n { role: \"pupil_R\", family: \"eye_R\" },\n { role: \"highlight_L\", family: \"eye_L\" },\n { role: \"highlight_R\", family: \"eye_R\" },\n { role: \"lash_lower_L\", family: \"eye_L\" },\n { role: \"lash_lower_R\", family: \"eye_R\" },\n { role: \"lash_L\", family: \"eye_L\" },\n { role: \"lash_R\", family: \"eye_R\" },\n { role: \"brow_L\", family: \"brow_L\" },\n { role: \"brow_R\", family: \"brow_R\" },\n { role: \"hair_front\", family: \"hair_front\" },\n];\n\nexport const REQUIRED_ROLES: readonly string[] = ROLE_TABLE.filter(\n (r) => r.required,\n).map((r) => r.role);\n\nconst SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));\n\nexport function roleSpec(role: string): RoleSpec & { i: number } {\n const spec = SPEC_BY_ROLE.get(role);\n if (spec === undefined) throw new Error(`auto-rig: unknown role \"${role}\"`);\n return spec;\n}\n\n/** Spelling variants seen on real layer sets, after the case and separator\n * normalisation below. */\nconst ALIASES: Record<string, string> = {\n eyebrow_L: \"brow_L\",\n eyebrow_R: \"brow_R\",\n eye_white_L: \"eye_L\",\n eye_white_R: \"eye_R\",\n};\n\n/** The role a file name names: without its extension, lower-cased, hyphens\n * and spaces as underscores, a trailing `_l` / `_r` side upper-cased, then\n * the aliases (\"Eye-L.png\" → \"eye_L\", \"eyebrow_R.png\" → \"brow_R\"). A PSD\n * layer name (no extension) names its role the same way. */\nfunction roleOf(fileName: string): string {\n const role = fileName\n .replace(/\\.[^.]+$/, \"\")\n .toLowerCase()\n .replace(/[-\\s]+/g, \"_\")\n .replace(/_([lr])$/, (_, s: string) => `_${s.toUpperCase()}`);\n return ALIASES[role] ?? role;\n}\n\n/**\n * Map file names to roles. Throws on an unknown role, a role named twice, or\n * a required role (`face`, `eye_L`, `eye_R`, `mouth`) missing.\n */\nexport function parseLayerRoles(\n fileNames: string[],\n): { role: string; fileName: string }[] {\n const seen = new Map<string, string>();\n const out: { role: string; fileName: string }[] = [];\n for (const fileName of fileNames) {\n const role = roleOf(fileName);\n if (!SPEC_BY_ROLE.has(role)) {\n throw new Error(\n `auto-rig: \"${fileName}\" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(\", \")})`,\n );\n }\n const prior = seen.get(role);\n if (prior !== undefined) {\n throw new Error(\n `auto-rig: role \"${role}\" is named twice (\"${prior}\" and \"${fileName}\")`,\n );\n }\n seen.set(role, fileName);\n out.push({ role, fileName });\n }\n const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));\n if (missing.length > 0) {\n throw new Error(\n `auto-rig: missing required role${missing.length > 1 ? \"s\" : \"\"} ${missing.join(\", \")}`,\n );\n }\n return out;\n}\n","/**\n * `generateIkiFromLayerSet`: role layers in, a rigged `.iki` out.\n *\n * The rig's shape is a 2D head rig's usual one (`profile.ts`): a torso that\n * only breathes; a head deformer that rolls about the chin and breathes; one\n * small warp grid per feature (each eye, each brow, the nose, the mouth),\n * translating and foreshortening it by its own lead over the plate; and the\n * plate, the hair and the blush moved by per-vertex keyforms of their own —\n * the plate as up to four islands of one drawing: a head that slides, a neck\n * that stays and two ears that lag. Blink, gaze, brows, mouth, breath and\n * hair sway are part warps and bindings under those. The model also declares\n * the default expressions and the Nod, Shake and Tilt motions\n * (`animations.ts`).\n */\n\nimport {\n IKI_FORMAT_VERSION,\n StandardParameter as P,\n parseIkiModel,\n type IkiBinding,\n type IkiDeformer,\n type IkiMesh,\n type IkiModel,\n type IkiParameter,\n type IkiPart,\n type IkiPhysics,\n type IkiWarp,\n} from \"@ikijs/format\";\nimport { DEFAULT_MOTIONS, defaultExpressions } from \"./animations\";\nimport { checkHeadEdges, checkLayers, checkStrandEdges } from \"./checks\";\nimport { renderedLander, sideIrises, solveContext } from \"./context\";\nimport { buildHeadFrame, type HeadFrame } from \"./head\";\nimport { buildFaceMesh, type Region } from \"./face-mesh\";\nimport {\n bh,\n boxOfLayer,\n bw,\n cellsFor,\n cx,\n cy,\n gridMesh,\n roundTo,\n unionBoxes,\n type Box,\n type Cells,\n} from \"./layout\";\nimport { roleSpec, ROLE_TABLE, type Family, type RoleSpec } from \"./roles\";\nimport { bake, lattice, X_STOPS, Y_STOPS, type Lattice } from \"./grid\";\nimport {\n chinSlide,\n earField,\n familyField,\n hairFrontBends,\n neckField,\n type Field,\n type HairFrontGrid,\n type TurnModel,\n} from \"./fields\";\nimport {\n buildTurn,\n checkedKeys,\n checkedNumber,\n fitTurn,\n resolveTurnTargets,\n TURN_TARGET_KEYS,\n turnReport,\n type ResolvedTargets,\n type TurnFit,\n} from \"./solve\";\nimport {\n blinkFold,\n browBindings,\n browReach,\n gazeBindings,\n gazeReach,\n hairHangWeight,\n hairSway,\n lashFold,\n localWarp,\n motionReach,\n mouthForm,\n mouthOpenGrow,\n mouthWiden,\n SWAY_RANGE,\n tiltHang,\n type Reach,\n} from \"./drivers\";\nimport {\n AMPLITUDE,\n ROLL_DEG,\n STYLE_KNOBS,\n resolveStyle,\n type ResolvedStyle,\n} from \"./profile\";\nimport { type GenerateOptions, type LayerInput } from \"./types\";\n\n/** Mesh cells per role. The plate's head island carries the chin's lead and\n * the jaw's narrowing; the hair only sways and hangs. */\nconst MESH_CELLS: Record<string, Cells> = {\n face: { px: 28, min: 4, max: 24 },\n // The front hair eases from riding the face to holding the outline.\n hair_front: { px: 32, min: 3, max: 24 },\n hair_back: { px: 56, min: 3, max: 18 },\n};\nconst NECK_CELLS: Cells = { px: 20, min: 3, max: 12 };\nconst FEATURE_MESH_CELLS: Cells = { px: 14, min: 2, max: 12 };\n\ntype GridFamily = \"eye_L\" | \"eye_R\" | \"brow_L\" | \"brow_R\" | \"nose\" | \"mouth\";\n\n/** Grid cells per feature: each only translates, foreshortens and tilts, so a\n * few cells carry it; they mostly hold the room its own motions need. */\nconst GRID_CELLS: Record<GridFamily, Cells> = {\n eye_L: { px: 24, min: 2, max: 8 },\n eye_R: { px: 24, min: 2, max: 8 },\n brow_L: { px: 32, min: 2, max: 6 },\n brow_R: { px: 32, min: 2, max: 6 },\n nose: { px: 16, min: 2, max: 8 },\n mouth: { px: 16, min: 2, max: 8 },\n};\nconst WARP_ID: Record<GridFamily, string> = {\n eye_L: \"eyeWarp_L\",\n eye_R: \"eyeWarp_R\",\n brow_L: \"browWarp_L\",\n brow_R: \"browWarp_R\",\n nose: \"noseWarp\",\n mouth: \"mouthWarp\",\n};\nconst isGridFamily = (f: Family): f is GridFamily => f in WARP_ID;\nconst GRID_PAD = 6;\n\ntype Grids = Map<Family, { lattice: Lattice; keyforms: number[][] }>;\n\nexport function generateIkiFromLayerSet(\n layers: LayerInput[],\n canvas: { width: number; height: number },\n options: GenerateOptions = {},\n): IkiModel {\n checkLayers(layers, canvas);\n const byRole = new Map(layers.map((l) => [l.role, l]));\n const has = (role: string) => byRole.has(role);\n const box = (role: string) => boxOfLayer(byRole.get(role)!);\n const hasNose = has(\"nose\");\n const plateHalf = byRole.get(\"face\")!.cropW / 2;\n\n checkHeadEdges(options.headEdges, byRole);\n checkStrandEdges(\n options.strandEdges,\n sideIrises(byRole),\n has(\"hair_front\") ? box(\"hair_front\") : undefined,\n );\n checkedKeys(\"style\", options.style, STYLE_KNOBS);\n const style = resolveStyle(options.style, (name, v, lo, hi) =>\n checkedNumber(name, v, lo, hi),\n );\n\n // Without a nose there is no turn to fit: the face turns on the profile,\n // inside its own outline. Every turn option — the cues, the measured head,\n // its edges and strands — is then inert; the edges and strands are still\n // checked against the layers, and the cues' object for a misspelt field.\n checkedKeys(\"turnTargets\", options.turnTargets, TURN_TARGET_KEYS);\n const targets: ResolvedTargets = hasNose\n ? resolveTurnTargets(options.turnTargets, plateHalf)\n : { given: new Set() };\n const turnOptions: GenerateOptions = hasNose ? options : {};\n const frameOptions = {\n headHalfWidth: targets.headHalfWidth,\n headEdges:\n targets.headHalfWidth !== undefined ? options.headEdges : undefined,\n };\n const solveFrame = buildHeadFrame(layers, frameOptions);\n\n // --- the turn ---\n const ctx = solveContext(solveFrame, byRole, turnOptions, hasNose);\n const boxes: TurnModel[\"boxes\"] = Object.fromEntries(\n ([\"eye_L\", \"eye_R\", \"brow_L\", \"brow_R\"] as const)\n .filter(has)\n .map((r) => [r, box(r)]),\n );\n const landmarks: Pick<\n TurnModel,\n \"boxes\" | \"noseAt\" | \"noseTopY\" | \"mouthAt\" | \"hairTop\" | \"hairFrontGrid\"\n > = {\n boxes,\n noseAt: ctx.noseAt,\n noseTopY: ctx.noseBox?.y1,\n mouthAt: ctx.mouthAt,\n hairTop: has(\"hair_front\") ? box(\"hair_front\").y1 : solveFrame.face.y1,\n // The field reads the grid the mesh is built on (the rebuilt frame below\n // differs only in the jaw's cut, which the grid does not read).\n hairFrontGrid: has(\"hair_front\")\n ? hairFrontGrid(box(\"hair_front\"), solveFrame, boxes)\n : undefined,\n };\n const build = (q: Parameters<typeof buildTurn>[2]) =>\n buildTurn(solveFrame, landmarks, q);\n // Without a nose there are no targets, but the art's room still bounds\n // the profile's turn.\n const fit: TurnFit = fitTurn(ctx, targets, style, build);\n\n // The jaw's cut takes the chin's shade only as far as the solved turn\n // keeps it inside the neck, so the frame is rebuilt with the chin's slide;\n // the two differ only in the cut, which the solve does not read.\n const frame = buildHeadFrame(layers, {\n ...frameOptions,\n chinSlide: chinSlide(fit.model),\n });\n const turn: TurnModel = { ...fit.model, frame };\n\n // --- parts, with the warps and bindings that are not the turn's ---\n const parts: IkiPart[] = [];\n const reach = new Map<string, Reach>();\n let regionOf: Region[] = [];\n let headStart = 0;\n for (const spec of ROLE_TABLE) {\n const layer = byRole.get(spec.role);\n if (layer === undefined) continue;\n const built = buildPart(\n spec,\n boxOfLayer(layer),\n parts.length,\n frame,\n byRole,\n style,\n landmarks.hairFrontGrid,\n );\n if (built.region !== undefined) {\n regionOf = built.region;\n headStart = built.headStart;\n }\n reach.set(spec.role, built.reach);\n parts.push(built.part);\n }\n\n // --- the features' grids ---\n const grids: Grids = new Map();\n for (const family of Object.keys(WARP_ID) as GridFamily[]) {\n const members = parts.filter((p) => roleSpec(p.id).family === family);\n if (members.length === 0) continue;\n const area = unionBoxes(\n members.map((p) => {\n const r = reach.get(p.id)!;\n const b = box(p.id);\n return {\n x0: b.x0 - r.left - GRID_PAD,\n x1: b.x1 + r.right + GRID_PAD,\n y0: b.y0 - r.bottom - GRID_PAD,\n y1: b.y1 + r.top + GRID_PAD,\n };\n }),\n );\n const cells = GRID_CELLS[family];\n const l = lattice(area, cells.px, cells.min, cells.max);\n grids.set(family, {\n lattice: l,\n keyforms: bake(l, familyField(turn, family)),\n });\n }\n\n // --- the plate, the blush and the hair: their own turn keyforms ---\n for (const part of parts) {\n const family = roleSpec(part.id).family;\n if (isGridFamily(family)) {\n part.deformer = WARP_ID[family];\n continue;\n }\n part.deformer = family === \"body\" ? \"bodyDeformer\" : \"headDeformer\";\n if (family === \"body\" || part.mesh === undefined) continue;\n const own = familyField(turn, family);\n const fieldOf: (i: number) => Field =\n part.id === \"face\" ? plateFields(turn, regionOf, own) : () => own;\n part.warps = [\n ...turnWarps(part.mesh, box(part.id), fieldOf),\n ...(part.warps ?? []),\n ];\n }\n\n const parameters = declareParameters(new Set(byRole.keys()));\n const model: IkiModel = {\n version: IKI_FORMAT_VERSION,\n name: \"auto-rigged\",\n canvas: { width: canvas.width, height: canvas.height },\n parameters,\n parts,\n deformers: deformers(frame, grids, has(\"body\") ? box(\"body\") : undefined),\n ...(has(\"hair_front\") ? { physics: hairPhysics() } : {}),\n expressions: defaultExpressions(new Set(parameters.map((p) => p.id))),\n motions: DEFAULT_MOTIONS,\n };\n\n // Reported only for a model that validates.\n const valid = parseIkiModel(model);\n if (hasNose && options.onTurnSolved) {\n options.onTurnSolved(\n turnReport(\n ctx,\n fit,\n renderedLander(turn, parts, grids, new Map([[\"face\", headStart]])),\n ),\n );\n }\n return valid;\n}\n\n/** A part's own turn and nod keyforms off its vertices' fields — split into\n * AngleX and AngleY, which add as the fields do. */\nfunction turnWarps(\n mesh: IkiMesh,\n b: Box,\n fieldOf: (i: number) => Field,\n): IkiWarp[] {\n return [\n localWarp(P.AngleX, mesh, b, X_STOPS, ([x, y], v, i) =>\n v === 0 ? [0, 0] : [fieldOf(i)(x, y, v, 0)[0], 0],\n ),\n localWarp(P.AngleY, mesh, b, Y_STOPS, ([x, y], v, i) =>\n v === 0 ? [0, 0] : [0, fieldOf(i)(x, y, 0, v)[1]],\n ),\n ];\n}\n\n/** The plate's islands each on their own motion: the head on the plate's\n * field, the ears lagging it, the neck still but for the shade under the\n * chin. */\nfunction plateFields(\n turn: TurnModel,\n region: Region[],\n head: Field,\n): (i: number) => Field {\n const ear = earField(turn);\n const neck = neckField(turn);\n return (i) =>\n region[i] === \"ear\" ? ear : region[i] === \"neck\" ? neck : head;\n}\n\n// --- parts ----------------------------------------------------------------------\n\nfunction buildPart(\n spec: RoleSpec,\n b: Box,\n order: number,\n frame: HeadFrame,\n byRole: Map<string, LayerInput>,\n style: ResolvedStyle,\n frontGrid: HairFrontGrid | undefined,\n): { part: IkiPart; reach: Reach; region?: Region[]; headStart: number } {\n const box = (role: string) => boxOfLayer(byRole.get(role)!);\n const part: IkiPart = {\n id: spec.role,\n color: [1, 1, 1, 1],\n width: bw(b),\n height: bh(b),\n transform: { x: cx(b), y: cy(b) },\n order,\n };\n const pivot: [number, number] = [frame.axisX, frame.chinY];\n const warps: IkiWarp[] = [];\n const bindings: IkiBinding[] = [];\n let extra: [number, number] = [0, 0];\n let mesh: IkiMesh | undefined;\n let region: Region[] | undefined;\n let headStart = 0;\n if (spec.role === \"face\") {\n const px = Math.min(MESH_CELLS.face.px, (2 * frame.wMax) / 14);\n const fm = buildFaceMesh(frame, b, { ...MESH_CELLS.face, px }, NECK_CELLS);\n mesh = fm.mesh;\n region = fm.region;\n headStart = fm.headStart;\n } else if (spec.role === \"hair_front\") {\n mesh = columnMesh(b, frontGrid!);\n } else if (spec.family !== \"body\") {\n const cells = MESH_CELLS[spec.role] ?? FEATURE_MESH_CELLS;\n // No coarser than a fraction of the head, whatever its size.\n const px = Math.min(cells.px, meshScale(spec.role, frame));\n mesh = gridMesh(\n cellsFor(bw(b), px, cells.min, cells.max),\n cellsFor(bh(b), px, cells.min, cells.max),\n );\n }\n if (mesh !== undefined) part.mesh = mesh;\n const side = spec.role.endsWith(\"_L\") ? \"L\" : \"R\";\n const eyeOpen = side === \"L\" ? P.EyeOpenLeft : P.EyeOpenRight;\n const hh = frame.hh;\n switch (spec.role) {\n case \"face\":\n if (region?.some((r) => r === \"neck\")) {\n const isNeck = region.map((r) => r === \"neck\");\n // The neck stays on the shoulders through the roll, and rises with\n // them on a breath (the head rises less).\n warps.push(\n tiltHang(mesh!, b, pivot, (_y, i) => (isNeck[i] ? 1 : 0)),\n localWarp(P.Breath, mesh!, b, [0, 1], (_p, v, i) =>\n v === 1 && isNeck[i]\n ? [0, (AMPLITUDE.breathBody - AMPLITUDE.breathHead) * hh]\n : [0, 0],\n ),\n );\n }\n break;\n case \"eye_L\":\n case \"eye_R\":\n warps.push(blinkFold(eyeOpen, mesh!, b, style.blink));\n break;\n case \"lash_lower_L\":\n case \"lash_lower_R\":\n warps.push(blinkFold(eyeOpen, mesh!, b, style.blink, box(`eye_${side}`)));\n break;\n case \"lash_L\":\n case \"lash_R\":\n warps.push(lashFold(eyeOpen, mesh!, b, box(`eye_${side}`), style.blink));\n break;\n case \"iris_L\":\n case \"iris_R\":\n case \"pupil_L\":\n case \"pupil_R\":\n case \"highlight_L\":\n case \"highlight_R\": {\n // A highlight is a reflection: it travels half as far.\n const share = spec.role.startsWith(\"highlight\") ? 0.5 : 1;\n const iris = byRole.get(`iris_${side}`);\n const irisW =\n iris !== undefined ? iris.cropW : 0.46 * bw(box(`eye_${side}`));\n bindings.push(...gazeBindings(irisW, share));\n extra = gazeReach(irisW, share);\n part.clip = { masks: [`eye_${side}`] };\n break;\n }\n case \"brow_L\":\n case \"brow_R\": {\n const r = browReach(hh);\n bindings.push(...browBindings(side, r));\n extra = [0.15 * bw(b), r + 0.15 * bw(b)];\n break;\n }\n case \"mouth\":\n warps.push(mouthForm(mesh!, b));\n if (byRole.has(\"mouth_open\")) {\n warps.push(mouthWiden(mesh!, b));\n // Two multiplying fades: the closed lips are gone by the time the\n // open drawing is half grown.\n bindings.push(\n { parameter: P.MouthOpen, channel: \"opacity\", from: 1, to: 0 },\n { parameter: P.MouthOpen, channel: \"opacity\", from: 1, to: 0 },\n );\n extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];\n } else {\n // One drawing only: stretch it open downward from its top lip, to\n // the profile's open height, and wider.\n const grow = Math.max(\n 0,\n (AMPLITUDE.mouthOpenHeight * bw(b)) / bh(b) - 1,\n );\n bindings.push(\n {\n parameter: P.MouthOpen,\n channel: \"scaleY\",\n from: 0,\n to: roundTo(grow, 0.01),\n },\n {\n parameter: P.MouthOpen,\n channel: \"scaleX\",\n from: 0,\n to: roundTo(AMPLITUDE.mouthOpenWidth - 1, 0.01),\n },\n {\n parameter: P.MouthOpen,\n channel: \"translateY\",\n from: 0,\n to: -roundTo((grow * bh(b)) / 2, 0.01),\n },\n );\n extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), grow * bh(b)];\n }\n break;\n case \"mouth_open\":\n warps.push(mouthForm(mesh!, b), mouthOpenGrow(mesh!, b));\n bindings.push({\n parameter: P.MouthOpen,\n channel: \"opacity\",\n from: 0,\n to: 1,\n });\n extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];\n break;\n case \"blush_L\":\n case \"blush_R\":\n bindings.push({\n parameter: P.Cheek,\n channel: \"opacity\",\n from: AMPLITUDE.blushRest,\n to: 1,\n });\n break;\n case \"hair_front\":\n case \"hair_back\":\n if (byRole.has(\"hair_front\")) {\n const amp = style.sway * AMPLITUDE.sway * hh;\n warps.push(\n hairSway(P.HairSwayX, mesh!, b, amp),\n hairSway(P.HairSwayZ, mesh!, b, amp),\n );\n }\n warps.push(tiltHang(mesh!, b, pivot, hairHangWeight(frame.chinY, b.y0)));\n break;\n }\n if (warps.length > 0) part.warps = warps;\n if (bindings.length > 0) part.bindings = bindings;\n return {\n part,\n reach: motionReach(part.warps, mesh, b, extra),\n region,\n headStart,\n };\n}\n\n/** The front hair's mesh grid over its box `b`: even cells no coarser than a\n * fraction of the head, plus columns where its follow bends, so the mesh\n * carries the bends exactly. */\nfunction hairFrontGrid(\n b: Box,\n frame: HeadFrame,\n boxes: TurnModel[\"boxes\"],\n): HairFrontGrid {\n const cells = MESH_CELLS.hair_front;\n const px = Math.min(cells.px, meshScale(\"hair_front\", frame));\n const cols = cellsFor(bw(b), px, cells.min, cells.max);\n const rows = cellsFor(bh(b), px, cells.min, cells.max);\n const { inner, left, right } = hairFrontBends(frame, boxes);\n const step = bw(b) / cols;\n const xs = Array.from({ length: cols + 1 }, (_, c) => b.x0 + c * step);\n for (const x of [\n frame.axisX - left,\n frame.axisX - inner,\n frame.axisX + inner,\n frame.axisX + right,\n ]) {\n if (x <= b.x0 + 0.25 || x >= b.x1 - 0.25) continue;\n const near = xs.findIndex((v) => Math.abs(v - x) < 0.3 * step);\n if (near > 0 && near < xs.length - 1) xs[near] = x;\n else if (near < 0) xs.push(x);\n }\n xs.sort((p, q) => p - q);\n const ys = Array.from(\n { length: rows + 1 },\n (_, r) => b.y1 - (bh(b) * r) / rows,\n );\n return { xs, ys };\n}\n\n/** A mesh over `b` on `grid`; row 0 on top, each cell split as `gridMesh`'s. */\nfunction columnMesh(b: Box, grid: HairFrontGrid): IkiMesh {\n const { xs } = grid;\n const rows = grid.ys.length - 1;\n const vertices: number[] = [];\n const uvs: number[] = [];\n for (let r = 0; r <= rows; r++) {\n for (const x of xs) {\n const u = (x - b.x0) / bw(b);\n vertices.push(roundTo(u - 0.5, 1e-5), roundTo(0.5 - r / rows, 1e-5));\n uvs.push(roundTo(u, 1e-5), roundTo(r / rows, 1e-5));\n }\n }\n const n = xs.length;\n const indices: number[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c + 1 < n; c++) {\n const tl = r * n + c;\n const bl = tl + n;\n indices.push(bl, bl + 1, tl, tl, bl + 1, tl + 1);\n }\n }\n return { vertices, uvs, indices };\n}\n\nfunction meshScale(role: string, frame: HeadFrame): number {\n switch (role) {\n case \"hair_front\":\n case \"hair_back\":\n // It only sways and hangs: smooth bends a coarse mesh carries.\n return Math.max(2, (frame.shellRight - frame.shellLeft) / 9);\n default:\n return Infinity;\n }\n}\n\n// --- deformers, parameters, physics ---------------------------------------------\n\nfunction deformers(\n frame: HeadFrame,\n grids: Grids,\n body: Box | undefined,\n): IkiDeformer[] {\n const out: IkiDeformer[] = [];\n if (body !== undefined) {\n out.push({\n id: \"bodyDeformer\",\n pivot: { x: roundTo(cx(body), 0.01), y: roundTo(body.y1, 0.01) },\n bindings: [\n {\n parameter: P.Breath,\n channel: \"translateY\",\n from: 0,\n to: roundTo(AMPLITUDE.breathBody * frame.hh, 0.01),\n },\n ],\n });\n }\n out.push({\n id: \"headDeformer\",\n pivot: { x: roundTo(frame.axisX, 0.01), y: roundTo(frame.chinY, 0.01) },\n bindings: [\n // AngleZ is clockwise-positive (Live2D's); a rotation is CCW-positive.\n { parameter: P.AngleZ, channel: \"rotate\", from: ROLL_DEG, to: -ROLL_DEG },\n {\n parameter: P.Breath,\n channel: \"translateY\",\n from: 0,\n to: roundTo(AMPLITUDE.breathHead * frame.hh, 0.01),\n },\n ],\n });\n for (const [family, g] of grids) {\n out.push({\n kind: \"warp\",\n id: WARP_ID[family as GridFamily],\n parent: \"headDeformer\",\n grid: {\n cols: g.lattice.cols,\n rows: g.lattice.rows,\n points: g.lattice.points,\n },\n warp2d: {\n parameter: P.AngleX,\n parameterY: P.AngleY,\n valuesX: X_STOPS,\n valuesY: Y_STOPS,\n keyforms2d: g.keyforms.map((offsets) => ({ offsets })),\n },\n });\n }\n return out;\n}\n\n/** Two springs, one per head axis the hair lags (a rig has one input). Each\n * settles at a modest share of its range, so a held turn or tilt leaves the\n * hair only a little swung. */\nfunction hairPhysics(): IkiPhysics[] {\n return [\n {\n id: \"hairSway\",\n input: { parameter: P.AngleX, weight: 1 },\n output: { parameter: P.HairSwayX, scale: 5 },\n mass: 1,\n stiffness: 30,\n damping: 3,\n },\n {\n id: \"hairTilt\",\n input: { parameter: P.AngleZ, weight: 1 },\n output: { parameter: P.HairSwayZ, scale: 8 },\n mass: 1,\n stiffness: 25,\n damping: 2.5,\n },\n ];\n}\n\nfunction declareParameters(roles: Set<string>): IkiParameter[] {\n const out: IkiParameter[] = [];\n const add = (\n id: string,\n name: string,\n min: number,\n max: number,\n def: number,\n ) => out.push({ id, name, min, max, default: def });\n add(P.AngleX, \"Head Angle\", -30, 30, 0);\n add(P.AngleY, \"Head Angle Y\", -30, 30, 0);\n add(P.AngleZ, \"Head Angle Z\", -30, 30, 0);\n add(P.EyeOpenLeft, \"Eye L\", 0, 1, 1);\n add(P.EyeOpenRight, \"Eye R\", 0, 1, 1);\n if ([...roles].some((r) => /^(iris|pupil|highlight)_/.test(r))) {\n add(P.EyeballX, \"Gaze X\", -1, 1, 0);\n add(P.EyeballY, \"Gaze Y\", -1, 1, 0);\n }\n add(P.MouthOpen, \"Mouth Open\", 0, 1, 0);\n add(P.MouthForm, \"Mouth Form\", -1, 1, 0);\n if (roles.has(\"brow_L\")) {\n add(P.BrowLeftY, \"Brow L Y\", -1, 1, 0);\n add(P.BrowLeftAngle, \"Brow L Angle\", -1, 1, 0);\n }\n if (roles.has(\"brow_R\")) {\n add(P.BrowRightY, \"Brow R Y\", -1, 1, 0);\n add(P.BrowRightAngle, \"Brow R Angle\", -1, 1, 0);\n }\n if (roles.has(\"blush_L\") || roles.has(\"blush_R\")) {\n add(P.Cheek, \"Cheek\", 0, 1, 0);\n }\n add(P.Breath, \"Breath\", 0, 1, 0);\n if (roles.has(\"hair_front\")) {\n add(P.HairSwayX, \"Hair Sway X\", -SWAY_RANGE, SWAY_RANGE, 0);\n add(P.HairSwayZ, \"Hair Sway Z\", -SWAY_RANGE, SWAY_RANGE, 0);\n }\n return out;\n}\n","/**\n * The expressions and motions an auto-rigged model declares, each with a\n * description a host (an LLM, say) picks it by.\n *\n * The values are our own, picked by eye on Bob and the long-haired character\n * (2026-10) from soft, medium and strong candidates. A term's\n * blend follows its parameter: EyeOpen multiplies, so the procedural blink\n * keeps running under it (at 0 the eyes stay shut); MouthOpenY overwrites,\n * and a host's lip-sync, written after the expression, wins; everything else\n * adds onto a parameter that rests at 0, clamped to its range. Only Shake\n * sets a fade; everything else plays with the format's\n * `DEFAULT_FADE_SECONDS`, capped at half a clip. No curve sets an\n * interpolation, so each is smooth.\n */\n\nimport {\n StandardParameter as P,\n type IkiExpression,\n type IkiExpressionParameter,\n type IkiMotionClip,\n} from \"@ikijs/format\";\n\n/** Both brows up (+) or down (−), in BrowY units. */\nfunction browsY(y: number): IkiExpressionParameter[] {\n return [\n { parameter: P.BrowLeftY, value: y, blend: \"add\" },\n { parameter: P.BrowRightY, value: y, blend: \"add\" },\n ];\n}\n\n/**\n * Both brows tilted as a mirror pair: + drops the inner ends (angry), − lifts\n * them (sad). Brow angles are raw per side and CCW-positive on screen, and the\n * character's left brow sits at +x, so its inner end is its screen-left end,\n * which a CCW turn drops; the right brow's inner end is its screen-right end,\n * which a CCW turn lifts. A mirror pair therefore takes opposite signs.\n */\nfunction browsTilt(innerDown: number): IkiExpressionParameter[] {\n return [\n { parameter: P.BrowLeftAngle, value: innerDown, blend: \"add\" },\n { parameter: P.BrowRightAngle, value: -innerDown, blend: \"add\" },\n ];\n}\n\nfunction cheek(value: number): IkiExpressionParameter {\n return { parameter: P.Cheek, value, blend: \"add\" };\n}\n\nconst BROWS = [P.BrowLeftY, P.BrowRightY, P.BrowLeftAngle, P.BrowRightAngle];\n\ninterface DefaultExpression extends IkiExpression {\n /** The parameters its look rests on: a model that declares none of them\n * could not show what the description promises, so it goes without. */\n needs?: string[];\n}\n\n// A model declares the brows, the gaze and Cheek only with the layers they\n// move, so `defaultExpressions` filters these terms, and leaves out an entry\n// whose look rests on a missing part: shy on the blush, angry and sad on the\n// brows. Every entry keeps a term on EyeOpen, MouthOpenY or MouthForm, which\n// the rig always declares, so a kept one is never emptied (`parseIkiModel`\n// would reject one that was).\nconst EXPRESSIONS: DefaultExpression[] = [\n {\n id: \"smile\",\n description:\n \"Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.\",\n parameters: [\n { parameter: P.MouthForm, value: 1, blend: \"add\" },\n ...browsY(0.25),\n cheek(0.4),\n ],\n },\n {\n id: \"laugh\",\n description:\n \"Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.\",\n parameters: [\n { parameter: P.EyeOpenLeft, value: 0, blend: \"multiply\" },\n { parameter: P.EyeOpenRight, value: 0, blend: \"multiply\" },\n { parameter: P.MouthForm, value: 1, blend: \"add\" },\n { parameter: P.MouthOpen, value: 0.8, blend: \"overwrite\" },\n ...browsY(0.4),\n cheek(0.65),\n ],\n },\n {\n id: \"angry\",\n description:\n \"Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.\",\n needs: BROWS,\n parameters: [\n ...browsY(-0.5),\n ...browsTilt(0.8),\n { parameter: P.MouthForm, value: -0.9, blend: \"add\" },\n ],\n },\n {\n id: \"sad\",\n description:\n \"Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.\",\n needs: BROWS,\n parameters: [\n ...browsY(0.35),\n ...browsTilt(-0.8),\n { parameter: P.MouthForm, value: -0.8, blend: \"add\" },\n ],\n },\n {\n id: \"surprised\",\n description:\n \"Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.\",\n parameters: [\n ...browsY(0.8),\n { parameter: P.MouthOpen, value: 0.9, blend: \"overwrite\" },\n ],\n },\n {\n id: \"shy\",\n description:\n \"Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.\",\n needs: [P.Cheek],\n parameters: [\n cheek(1),\n // Gaze down.\n { parameter: P.EyeballY, value: -0.65, blend: \"add\" },\n { parameter: P.MouthForm, value: 0.4, blend: \"add\" },\n ...browsTilt(-0.25),\n ],\n },\n];\n\n/** The default expressions a model with the `declared` parameters can show,\n * each keeping only its terms on them, in table order. */\nexport function defaultExpressions(\n declared: ReadonlySet<string>,\n): IkiExpression[] {\n return EXPRESSIONS.filter(\n (e) => e.needs === undefined || e.needs.some((id) => declared.has(id)),\n ).map(({ needs: _needs, ...e }) => ({\n ...e,\n parameters: e.parameters.filter((t) => declared.has(t.parameter)),\n }));\n}\n\n/**\n * The head motions, one clip per group: a host plays (`Nod`, 0). AngleX,\n * AngleY and AngleZ are always declared, so these need no filter. AngleY −30\n * looks down and +30 up, so a nod dips negative; AngleZ + tilts the top of\n * the head toward the viewer's right. No `Idle` group, so the procedural idle\n * stays whole.\n */\nexport const DEFAULT_MOTIONS: Record<string, IkiMotionClip[]> = {\n Nod: [\n {\n description: \"Nods yes: agreement, acknowledgement, understanding.\",\n duration: 1,\n curves: [\n {\n parameter: P.AngleY,\n keys: [\n [0, 0],\n [0.3, -18],\n [0.6, 4],\n [0.8, -1],\n [1, 0],\n ],\n },\n ],\n },\n ],\n Shake: [\n {\n description: \"Shakes the head no: disagreement, refusal, disbelief.\",\n duration: 1.2,\n // The first swing peaks at 0.2 s, which the default fade would still\n // be damping.\n fadeIn: 0.15,\n curves: [\n {\n parameter: P.AngleX,\n keys: [\n [0, 0],\n [0.2, -18],\n [0.45, 18],\n [0.7, -16],\n [0.95, 10],\n [1.2, 0],\n ],\n },\n ],\n },\n ],\n Tilt: [\n {\n description:\n \"Tilts the head to one side and back: curiosity, puzzlement, a question.\",\n duration: 1.4,\n curves: [\n {\n parameter: P.AngleZ,\n keys: [\n [0, 0],\n [0.35, 20],\n [1, 20],\n [1.4, 0],\n ],\n },\n ],\n },\n ],\n};\n","import type { IkiMesh } from \"@ikijs/format\";\nimport type { LayerInput } from \"./types\";\n\n/** An axis-aligned box in model space (origin canvas centre, +y up). */\nexport interface Box {\n x0: number;\n x1: number;\n /** Bottom edge (smaller y). */\n y0: number;\n /** Top edge (larger y). */\n y1: number;\n}\n\nexport function boxOfLayer(layer: LayerInput): Box {\n return boxOfPixels(layer.bbox, layer.canvasW, layer.canvasH);\n}\n\nexport function boxOfPixels(\n b: { x: number; y: number; w: number; h: number },\n canvasW: number,\n canvasH: number,\n): Box {\n return {\n x0: b.x - canvasW / 2,\n x1: b.x + b.w - canvasW / 2,\n y0: canvasH / 2 - (b.y + b.h),\n y1: canvasH / 2 - b.y,\n };\n}\n\nexport const cx = (b: Box): number => (b.x0 + b.x1) / 2;\nexport const cy = (b: Box): number => (b.y0 + b.y1) / 2;\nexport const bw = (b: Box): number => b.x1 - b.x0;\nexport const bh = (b: Box): number => b.y1 - b.y0;\n\nexport function unionBoxes(boxes: Box[]): Box {\n return {\n x0: Math.min(...boxes.map((b) => b.x0)),\n x1: Math.max(...boxes.map((b) => b.x1)),\n y0: Math.min(...boxes.map((b) => b.y0)),\n y1: Math.max(...boxes.map((b) => b.y1)),\n };\n}\n\nexport const clamp = (v: number, lo: number, hi: number): number =>\n v < lo ? lo : v > hi ? hi : v;\n\nexport function smoothstep(e0: number, e1: number, v: number): number {\n if (e1 === e0) return v < e0 ? 0 : 1;\n const t = clamp((v - e0) / (e1 - e0), 0, 1);\n return t * t * (3 - 2 * t);\n}\n\nexport const DEG = Math.PI / 180;\n\n/** Round for the written model: every number the rig emits goes through one\n * of these, so the file stays small and a re-rig is byte-stable. */\nexport const roundTo = (v: number, step: number): number => {\n const r = Math.round(v / step) * step;\n // Normalise -0 and float noise from the multiply (0.30000000000000004).\n return r === 0\n ? 0\n : Number(r.toFixed(Math.max(0, -Math.floor(Math.log10(step)))));\n};\n\n/** How finely a mesh or grid is cut: about `px` per cell, `min`…`max` cells\n * a side. */\nexport interface Cells {\n /** Target cell size, px. */\n px: number;\n min: number;\n max: number;\n}\n\n/** Cells for a span of `size` px at about `cell` px each. */\nexport function cellsFor(\n size: number,\n cell: number,\n min: number,\n max: number,\n): number {\n return clamp(Math.ceil(size / cell), min, max);\n}\n\n/**\n * A regular grid mesh in part-local ±0.5 space, row 0 on top — the layout of\n * `createGridMesh`, with vertex coordinates rounded so the file stays small.\n */\nexport function gridMesh(cols: number, rows: number): IkiMesh {\n const vertices: number[] = [];\n const uvs: number[] = [];\n for (let r = 0; r <= rows; r++) {\n for (let c = 0; c <= cols; c++) {\n vertices.push(\n roundTo(c / cols - 0.5, 1e-5),\n roundTo(0.5 - r / rows, 1e-5),\n );\n uvs.push(roundTo(c / cols, 1e-5), roundTo(r / rows, 1e-5));\n }\n }\n const indices: number[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tl = r * (cols + 1) + c;\n const tr = tl + 1;\n const bl = tl + cols + 1;\n const br = bl + 1;\n indices.push(bl, br, tl, tl, br, tr);\n }\n }\n return { vertices, uvs, indices };\n}\n\n/** Model-space position of each mesh vertex of a part laid over `box`. */\nexport function meshPoints(mesh: IkiMesh, box: Box): [number, number][] {\n const out: [number, number][] = [];\n for (let i = 0; i < mesh.vertices.length; i += 2) {\n out.push([\n cx(box) + mesh.vertices[i] * bw(box),\n cy(box) + mesh.vertices[i + 1] * bh(box),\n ]);\n }\n return out;\n}\n","/**\n * Input checks. A malformed layer is a host bug and throws a plain `Error`;\n * malformed turn options come from a caller and throw `TurnTargetError`, which\n * `@ikijs/mcp` reports as `{ ok: false }` rather than a crash.\n */\n\nimport { boxOfLayer, cx, type Box } from \"./layout\";\nimport { REQUIRED_ROLES, roleSpec } from \"./roles\";\nimport {\n TurnTargetError,\n type GenerateOptions,\n type HeadEdges,\n type LayerInput,\n} from \"./types\";\n\nconst finite = (v: unknown): v is number =>\n typeof v === \"number\" && Number.isFinite(v);\n\nconst isObject = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null;\n\n/** The face plate's mesh has at most 24 cells a side; at this size each is\n * still a pixel, so none collapses to nothing. */\nconst MIN_FACE_PX = 24;\n\nexport function checkLayers(\n layers: LayerInput[],\n canvas: { width: number; height: number },\n): void {\n if (!Array.isArray(layers) || layers.length === 0) {\n throw new Error(\n \"auto-rig: generateIkiFromLayerSet: layers must be a non-empty array\",\n );\n }\n if (!(finite(canvas?.width) && canvas.width > 0)) {\n throw new Error(\"auto-rig: canvas.width must be a positive number\");\n }\n if (!(finite(canvas?.height) && canvas.height > 0)) {\n throw new Error(\"auto-rig: canvas.height must be a positive number\");\n }\n const seen = new Set<string>();\n for (const l of layers) {\n roleSpec(l.role);\n if (seen.has(l.role)) {\n throw new Error(`auto-rig: role \"${l.role}\" appears twice`);\n }\n seen.add(l.role);\n const at = `auto-rig: layer \"${l.fileName}\"`;\n const { x, y, w, h } = l.bbox ?? {};\n if (\n ![x, y, w, h].every(finite) ||\n w <= 0 ||\n h <= 0 ||\n x < 0 ||\n y < 0 ||\n x + w > canvas.width ||\n y + h > canvas.height\n ) {\n throw new Error(\n `${at} has a bbox outside its ${canvas.width}x${canvas.height} canvas`,\n );\n }\n if (l.canvasW !== canvas.width || l.canvasH !== canvas.height) {\n throw new Error(\n `${at} was measured on a ${l.canvasW}x${l.canvasH} canvas, not ${canvas.width}x${canvas.height}`,\n );\n }\n // The crop the atlas holds is the bbox: the part is sized off one, the\n // plate's stand-in half-width off the other.\n if (l.cropW !== w || l.cropH !== h) {\n throw new Error(\n `${at}: crop ${l.cropW}x${l.cropH} is not its bbox ${w}x${h}`,\n );\n }\n if (l.role === \"face\" && (w < MIN_FACE_PX || h < MIN_FACE_PX)) {\n throw new Error(\n `${at}: the face is ${w}x${h} px; the face plate needs at least ${MIN_FACE_PX} px each way to be meshed`,\n );\n }\n if (l.rowHalfWidths !== undefined) {\n const rows = l.rowHalfWidths;\n if (!Array.isArray(rows) || rows.length !== h) {\n throw new Error(\n `${at}: rowHalfWidths must have one entry per crop row (${h})`,\n );\n }\n rows.forEach((v, i) => {\n if (!finite(v) || v < 0 || v > w / 2 + 0.5) {\n throw new Error(\n `${at}: rowHalfWidths[${i}] ${v} is not a half-width inside its crop`,\n );\n }\n });\n }\n if (l.rowRuns !== undefined) {\n const rows = l.rowRuns;\n if (!Array.isArray(rows) || rows.length !== h) {\n throw new Error(\n `${at}: rowRuns must have one entry per crop row (${h})`,\n );\n }\n rows.forEach((runs, i) => {\n if (\n !Array.isArray(runs) ||\n runs.length % 2 !== 0 ||\n !runs.every(\n (c, k) =>\n Number.isInteger(c) &&\n c >= x &&\n c <= x + w &&\n (k === 0 || c > runs[k - 1]),\n )\n ) {\n throw new Error(\n `${at}: rowRuns[${i}] ${JSON.stringify(runs)} is not an even-length, strictly increasing list of columns inside its crop (${x}..${x + w})`,\n );\n }\n });\n }\n if (l.jawRows !== undefined) {\n const cols = l.jawRows;\n if (!Array.isArray(cols) || cols.length !== w) {\n throw new Error(\n `${at}: jawRows must have one entry per crop column (${w})`,\n );\n }\n cols.forEach((v, i) => {\n if (!Number.isInteger(v) || (v !== -1 && (v < y || v >= y + h))) {\n throw new Error(\n `${at}: jawRows[${i}] ${v} is neither -1 nor a row of its crop`,\n );\n }\n });\n }\n if (l.denseCore !== undefined) {\n const c = l.denseCore;\n if (\n ![c.x, c.y, c.w, c.h].every(finite) ||\n c.w <= 0 ||\n c.h <= 0 ||\n c.x < x - 1 ||\n c.y < y - 1 ||\n c.x + c.w > x + w + 1 ||\n c.y + c.h > y + h + 1\n ) {\n throw new Error(`${at}: denseCore is not a box inside its crop`);\n }\n }\n }\n const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));\n if (missing.length > 0) {\n throw new Error(`auto-rig: missing required role(s) ${missing.join(\", \")}`);\n }\n}\n\n/** Each entry names a layer of this set; the outermost left edge lies left\n * of the face, the outermost right edge right of it. */\nexport function checkHeadEdges(\n edges: HeadEdges | undefined,\n byRole: Map<string, LayerInput>,\n): void {\n if (edges === undefined) return;\n if (!isObject(edges))\n throw new TurnTargetError(\"headEdges must be an object\");\n for (const side of [\"left\", \"right\"] as const) {\n const list: unknown = edges[side];\n if (!Array.isArray(list)) {\n throw new TurnTargetError(`headEdges.${side} must be an array`);\n }\n list.forEach((e: unknown, i) => {\n if (!isObject(e) || typeof e.role !== \"string\" || !byRole.has(e.role)) {\n throw new TurnTargetError(\n `headEdges.${side}[${i}].role is not a layer in this set`,\n );\n }\n if (!finite(e.x)) {\n throw new TurnTargetError(\n `headEdges.${side}[${i}].x must be a finite number`,\n );\n }\n });\n }\n if (edges.left.length > 0 && edges.right.length > 0) {\n const axis = cx(boxOfLayer(byRole.get(\"face\")!));\n const left = Math.min(...edges.left.map((e) => e.x));\n const right = Math.max(...edges.right.map((e) => e.x));\n if (!(left < axis && axis < right)) {\n throw new TurnTargetError(\n `headEdges: the left edge ${left} and the right edge ${right} do not bracket the face (x ${axis})`,\n );\n }\n }\n}\n\n/** Strand edges describe the irises this set has, against bangs it has, on\n * a row both cover: each side's iris span inside its crop, outer edge\n * strictly outward; the run inside the bangs' crop, its outer end strictly\n * outward of the iris's centre and of its face-side end, and that end short\n * of the other iris's centre (a run reaching it is a fringe: `null`). */\nexport function checkStrandEdges(\n strand: GenerateOptions[\"strandEdges\"],\n irises: { left?: Box; right?: Box },\n hair: Box | undefined,\n): void {\n if (strand === undefined) return;\n if (!isObject(strand)) {\n throw new TurnTargetError(\"strandEdges must be an object\");\n }\n for (const side of [\"left\", \"right\"] as const) {\n const s: unknown = strand[side];\n if (s === undefined) continue;\n const at = `strandEdges.${side}`;\n if (!isObject(s)) throw new TurnTargetError(`${at} must be an object`);\n if (hair === undefined) {\n throw new TurnTargetError(\n `${at} names a bangs' run, but this layer set has no hair_front`,\n );\n }\n for (const k of [\"y\", \"irisOuter\", \"irisInner\", \"runOuter\"] as const) {\n if (!finite(s[k])) {\n throw new TurnTargetError(`${at}.${k} must be a finite number`);\n }\n }\n if (s.runFace !== null && !finite(s.runFace)) {\n throw new TurnTargetError(\n `${at}.runFace must be a finite number or null`,\n );\n }\n const iris = irises[side];\n const other = irises[side === \"left\" ? \"right\" : \"left\"];\n if (iris === undefined || other === undefined) {\n throw new TurnTargetError(\n `${at} names an iris this layer set does not have`,\n );\n }\n const y = s.y as number;\n const outer = s.irisOuter as number;\n const inner = s.irisInner as number;\n const runOuter = s.runOuter as number;\n const runFace = s.runFace as number | null;\n // Outward is −x on the left side, +x on the right.\n const sign = side === \"left\" ? -1 : 1;\n if (y < iris.y0 || y > iris.y1 || y < hair.y0 || y > hair.y1) {\n throw new TurnTargetError(\n `${at}.y ${y} is not on a row of both its iris and hair_front`,\n );\n }\n for (const [k, x] of [\n [\"irisOuter\", outer],\n [\"irisInner\", inner],\n ] as const) {\n if (x < iris.x0 || x > iris.x1) {\n throw new TurnTargetError(`${at}.${k} ${x} is off its iris's crop`);\n }\n }\n if (sign * (outer - inner) <= 0) {\n throw new TurnTargetError(\n `${at}.irisOuter ${outer} is not strictly outward of irisInner ${inner}`,\n );\n }\n for (const [k, x] of [\n [\"runOuter\", runOuter],\n [\"runFace\", runFace],\n ] as const) {\n if (x !== null && (x < hair.x0 || x > hair.x1)) {\n throw new TurnTargetError(`${at}.${k} ${x} is off hair_front's crop`);\n }\n }\n if (sign * (runOuter - cx(iris)) <= 0) {\n throw new TurnTargetError(\n `${at}.runOuter ${runOuter} is not strictly outward of its iris's centre`,\n );\n }\n if (runFace !== null && sign * (runOuter - runFace) <= 0) {\n throw new TurnTargetError(\n `${at}.runOuter ${runOuter} is not strictly outward of runFace ${runFace}`,\n );\n }\n if (runFace !== null && sign * (runFace - cx(other)) <= 0) {\n throw new TurnTargetError(\n `${at}.runFace ${runFace} reaches the other iris's centre; a run that does is a fringe, runFace null`,\n );\n }\n }\n}\n","/**\n * What the turn solve reads off the layers — the cue rows, the silhouette,\n * the landmarks — and the lander that reads a finished rig back the way the\n * engine renders it.\n */\n\nimport { StandardParameter as P, type IkiPart } from \"@ikijs/format\";\nimport type { HeadFrame } from \"./head\";\nimport {\n boxOfLayer,\n boxOfPixels,\n bw,\n cx,\n cy,\n meshPoints,\n unionBoxes,\n type Box,\n} from \"./layout\";\nimport { roleSpec, type Family } from \"./roles\";\nimport { blendStops, keyformAt, land, type Lattice } from \"./grid\";\nimport { familyField, type TurnModel } from \"./fields\";\nimport type { IrisRow, Lander, SolveContext } from \"./solve\";\nimport type { GenerateOptions, IrisStrand, LayerInput } from \"./types\";\n\ninterface SideBox {\n role: string;\n box: Box;\n}\n\n/** A pair of roles as they sit on the canvas, the −x one first — which is\n * the character's right by convention, but the art decides. */\nfunction sidePair(\n byRole: Map<string, LayerInput>,\n a: string,\n b: string,\n): { left: SideBox; right: SideBox } | undefined {\n const la = byRole.get(a);\n const lb = byRole.get(b);\n if (la === undefined || lb === undefined) return undefined;\n const [lo, hi] = [\n { role: a, box: boxOfLayer(la) },\n { role: b, box: boxOfLayer(lb) },\n ].sort((p, q) => cx(p.box) - cx(q.box));\n return { left: lo, right: hi };\n}\n\n/** The irises on each side of the face, by x. */\nexport function sideIrises(byRole: Map<string, LayerInput>): {\n left?: Box;\n right?: Box;\n} {\n const pair = sidePair(byRole, \"iris_L\", \"iris_R\");\n return pair === undefined\n ? {}\n : { left: pair.left.box, right: pair.right.box };\n}\n\nexport function solveContext(\n frame: HeadFrame,\n byRole: Map<string, LayerInput>,\n options: GenerateOptions,\n hasNose: boolean,\n): SolveContext {\n const box = (role: string) => boxOfLayer(byRole.get(role)!);\n // The cue rows: each iris's painted span on its centre row, as measured;\n // failing that its crop less the one-pixel alpha margin; failing irises,\n // the eye whites.\n const row = (\n s: SideBox,\n strand: IrisStrand | undefined,\n sideSign: -1 | 1,\n ): IrisRow => {\n if (strand !== undefined) {\n const lo = sideSign < 0 ? strand.irisOuter : strand.irisInner;\n const hi = sideSign < 0 ? strand.irisInner : strand.irisOuter;\n return { role: s.role, lo, hi, y: strand.y };\n }\n const inset = bw(s.box) > 4 ? 1 : 0;\n return {\n role: s.role,\n lo: s.box.x0 + inset,\n hi: s.box.x1 - inset,\n y: cy(s.box),\n };\n };\n const eyes = sidePair(byRole, \"eye_L\", \"eye_R\")!;\n const irises = sidePair(byRole, \"iris_L\", \"iris_R\");\n const pair = irises ?? eyes;\n const strand = irises ? options.strandEdges : undefined;\n const left = row(pair.left, strand?.left, -1);\n const right = row(pair.right, strand?.right, 1);\n\n // The silhouette at the eye row: the layers the measurer found there, each\n // landing through its own motion; without them, the held outline or the\n // plate's own painted edge.\n let candidates: SolveContext[\"candidates\"];\n const edges = options.headEdges;\n if (\n frame.hairShell &&\n edges &&\n edges.left.length > 0 &&\n edges.right.length > 0\n ) {\n candidates = {\n left: edges.left.map((e) => ({ role: e.role, x: e.x })),\n // A right edge names its outermost pixel column; the boundary is one on.\n right: edges.right.map((e) => ({ role: e.role, x: e.x + 1 })),\n };\n } else if (frame.hairShell) {\n candidates = {\n left: [{ role: \"hair_back\", x: frame.shellLeft }],\n right: [{ role: \"hair_back\", x: frame.shellRight }],\n };\n } else {\n const w = frame.paintedHalfAt(frame.eyeY);\n candidates = {\n left: [{ role: \"face\", x: frame.axisX - w }],\n right: [{ role: \"face\", x: frame.axisX + w }],\n };\n }\n const restHalf =\n (Math.max(...candidates.right.map((c) => c.x)) -\n Math.min(...candidates.left.map((c) => c.x))) /\n 2;\n\n const nose = byRole.get(\"nose\");\n let noseAt: { x: number; y: number } | undefined;\n let noseBox: Box | undefined;\n if (hasNose && nose !== undefined) {\n noseBox = nose.denseCore\n ? boxOfPixels(nose.denseCore, nose.canvasW, nose.canvasH)\n : boxOfLayer(nose);\n noseAt = { x: cx(noseBox), y: cy(noseBox) };\n }\n const mouthBox = byRole.has(\"mouth_open\")\n ? unionBoxes([box(\"mouth\"), box(\"mouth_open\")])\n : box(\"mouth\");\n const m = box(\"mouth\");\n return {\n frame,\n left,\n right,\n candidates,\n restHalf,\n strand,\n hasHairFront: byRole.has(\"hair_front\"),\n eyeBoxes: { left: eyes.left.box, right: eyes.right.box },\n noseAt,\n noseBox,\n mouthAt: { x: cx(m), y: cy(m) },\n mouthBox,\n };\n}\n\n/**\n * Lands a point the way the engine draws it: the part's mesh vertices go\n * through its baked grid at the stop (or take its own AngleX keyform), and\n * the point is read linearly off the mesh triangle it rests in — the GPU's\n * interpolation, not the field's. `from` names, per part, the first index of\n * the triangles a point may land on (the face's head island).\n */\nexport function renderedLander(\n turn: TurnModel,\n parts: IkiPart[],\n grids: Map<Family, { lattice: Lattice; keyforms: number[][] }>,\n from: Map<string, number> = new Map(),\n): Lander {\n const analytic = new Map<Family, ReturnType<typeof familyField>>();\n const landed = new Map<string, number[]>();\n const field = (role: string) => {\n const family = roleSpec(role).family;\n let f = analytic.get(family);\n if (f === undefined) analytic.set(family, (f = familyField(turn, family)));\n return f;\n };\n return (role, x, y, ax) => {\n const family = roleSpec(role).family;\n const part = parts.find((p) => p.id === role);\n const g = grids.get(family);\n const warp = part?.warps?.find((w) => w.parameter === P.AngleX);\n if (part === undefined || part.mesh === undefined || (!g && !warp)) {\n return x + field(role)(x, y, ax, 0)[0];\n }\n const box: Box = {\n x0: part.transform.x - part.width / 2,\n x1: part.transform.x + part.width / 2,\n y0: part.transform.y - part.height / 2,\n y1: part.transform.y + part.height / 2,\n };\n const rest = meshPoints(part.mesh, box);\n const key = `${role}@${ax}`;\n let xs = landed.get(key);\n if (xs === undefined) {\n if (g) {\n const offsets = keyformAt(g.keyforms, ax);\n xs = rest.map(([px, py]) => land(g.lattice, offsets, px, py)[0]);\n } else {\n const k = warp!.keyforms;\n const offsets = blendStops(\n k.map((kf) => kf.value),\n k.map((kf) => kf.offsets),\n ax,\n );\n xs = rest.map(([px], i) => px + offsets[2 * i] * bw(box));\n }\n landed.set(key, xs);\n }\n const idx = part.mesh.indices;\n for (let t = from.get(role) ?? 0; t < idx.length; t += 3) {\n const [a, b, c] = [idx[t], idx[t + 1], idx[t + 2]];\n const [ax0, ay0] = rest[a];\n const [bx0, by0] = rest[b];\n const [cx0, cy0] = rest[c];\n const d = (by0 - cy0) * (ax0 - cx0) + (cx0 - bx0) * (ay0 - cy0);\n if (Math.abs(d) < 1e-9) continue;\n const u = ((by0 - cy0) * (x - cx0) + (cx0 - bx0) * (y - cy0)) / d;\n const v = ((cy0 - ay0) * (x - cx0) + (ax0 - cx0) * (y - cy0)) / d;\n const w = 1 - u - v;\n if (u < -1e-6 || v < -1e-6 || w < -1e-6) continue;\n return u * xs[a] + v * xs[b] + w * xs[c];\n }\n // Off the mesh (between islands, or past a trimmed cell): the field.\n return x + field(role)(x, y, ax, 0)[0];\n };\n}\n","/**\n * Warp grids: a family's rest lattice, its turn × nod keyforms, and the\n * landing of a point through them — the same bind-to-rest-cell, sample-the-\n * deformed-cell bilinear the engine renders with, so a cue measured here is\n * the cue the render shows.\n */\n\nimport type { Field } from \"./fields\";\nimport { cellsFor, clamp, roundTo, type Box } from \"./layout\";\n\n/** AngleX and AngleY stops: every motion is linear in each on either side of\n * rest, so the extremes and rest carry it exactly, and the bilinear blend\n * between them adds a turn and a nod. */\nexport const X_STOPS = [-30, 0, 30];\nexport const Y_STOPS = [-30, 0, 30];\n\nexport interface Lattice {\n box: Box;\n cols: number;\n rows: number;\n /** Rest points, row-major, row 0 on top. */\n points: number[];\n}\n\nexport function lattice(\n box: Box,\n cell: number,\n min: number,\n max: number,\n): Lattice {\n const cols = cellsFor(box.x1 - box.x0, cell, min, max);\n const rows = cellsFor(box.y1 - box.y0, cell, min, max);\n const points: number[] = [];\n for (let r = 0; r <= rows; r++) {\n const y = box.y1 - ((box.y1 - box.y0) * r) / rows;\n for (let c = 0; c <= cols; c++) {\n points.push(\n roundTo(box.x0 + ((box.x1 - box.x0) * c) / cols, 0.01),\n roundTo(y, 0.01),\n );\n }\n }\n return { box, cols, rows, points };\n}\n\n/** Keyforms for every (X_STOPS[i], Y_STOPS[j]) stop, filed at j·|X| + i. */\nexport function bake(l: Lattice, field: Field): number[][] {\n const out: number[][] = [];\n for (const ay of Y_STOPS) {\n for (const ax of X_STOPS) {\n const offsets: number[] = [];\n for (let k = 0; k < l.points.length; k += 2) {\n if (ax === 0 && ay === 0) {\n offsets.push(0, 0);\n continue;\n }\n const [dx, dy] = field(l.points[k], l.points[k + 1], ax, ay);\n offsets.push(roundTo(dx, 0.1), roundTo(dy, 0.1));\n }\n out.push(offsets);\n }\n }\n return out;\n}\n\n/** The offsets at (ax, AngleY 0): the engine's linear blend between the two\n * AngleX stops around it. */\nexport function keyformAt(keyforms: number[][], ax: number): number[] {\n const j = Y_STOPS.indexOf(0);\n const row = X_STOPS.map((_, i) => keyforms[j * X_STOPS.length + i]);\n return blendStops(X_STOPS, row, ax);\n}\n\n/** Linear blend of per-stop offset arrays at `v` (clamped to the stops). */\nexport function blendStops(\n values: number[],\n offsets: number[][],\n v: number,\n): number[] {\n const x = clamp(v, values[0], values[values.length - 1]);\n let i = 0;\n while (i < values.length - 2 && x > values[i + 1]) i++;\n const t = (x - values[i]) / (values[i + 1] - values[i]);\n return offsets[i].map((o, k) => o + (offsets[i + 1][k] - o) * t);\n}\n\n/** Where a rest point lands on the deformed grid (rest + offsets). */\nexport function land(\n l: Lattice,\n offsets: number[],\n x: number,\n y: number,\n): [number, number] {\n const { cols, rows, points } = l;\n const stride = cols + 1;\n let col = cols - 1;\n for (let c = 0; c < cols; c++) {\n if (x < points[(c + 1) * 2]) {\n col = c;\n break;\n }\n }\n let row = rows - 1;\n for (let r = 0; r < rows; r++) {\n if (y > points[(r + 1) * stride * 2 + 1]) {\n row = r;\n break;\n }\n }\n const x0 = points[col * 2];\n const x1 = points[(col + 1) * 2];\n const yT = points[row * stride * 2 + 1];\n const yB = points[(row + 1) * stride * 2 + 1];\n const s = clamp((x - x0) / (x1 - x0), 0, 1);\n const t = clamp((yT - y) / (yT - yB), 0, 1);\n const at = (r: number, c: number): [number, number] => {\n const k = (r * stride + c) * 2;\n return [points[k] + offsets[k], points[k + 1] + offsets[k + 1]];\n };\n const p00 = at(row, col);\n const p10 = at(row, col + 1);\n const p01 = at(row + 1, col);\n const p11 = at(row + 1, col + 1);\n const topX = p00[0] + (p10[0] - p00[0]) * s;\n const topY = p00[1] + (p10[1] - p00[1]) * s;\n const botX = p01[0] + (p11[0] - p01[0]) * s;\n const botY = p01[1] + (p11[1] - p01[1]) * s;\n return [topX + (botX - topX) * t, topY + (botY - topY) * t];\n}\n","/**\n * The head's frame of reference, read off the layers: where its turn axis\n * runs, its eye row and chin (and so the profile's head unit), the face\n * plate's painted rows, the neck the face layer carries and the jaw line that\n * separates the two, and the silhouette the measured head draws.\n */\n\nimport { boxOfLayer, clamp, cx, cy, type Box } from \"./layout\";\nimport type { HeadEdges, LayerInput } from \"./types\";\n\nexport interface Neck {\n /** Where the jaw's outline meets the neck's sides, model y. */\n topY: number;\n /** The neck's half-width there. */\n half: number;\n /** The widest the neck gets below that (a flare into the collar). */\n span: number;\n /** Its narrowest, between the two: where its outline runs. */\n waist: number;\n /** Under a measured jaw stroke, given the chin's slide: how far from the\n * axis the cut draws the end of the chin's shade band (see JAW_SHADE). */\n bandEnd?: number;\n}\n\n/** Ears the face layer paints on the plate's sides: a band of rows where the\n * outline juts out past the head's own and back in. */\nexport interface Ears {\n /** The band's top and bottom rows, model y. */\n top: number;\n bottom: number;\n /** The head's own half-width on row `y` of the band, under the ear. */\n attachAt(y: number): number;\n /** The ears' widest half-width. */\n outer: number;\n}\n\nexport interface HeadFrame {\n canvasW: number;\n canvasH: number;\n face: Box;\n /** The head's vertical centre line, model x (the face plate's centre). */\n axisX: number;\n /** The eye row (the iris centres), model y. */\n eyeY: number;\n mouthY: number;\n /** The chin tip — the jaw outline's lowest point — model y. */\n chinY: number;\n /** The profile's head unit `hh`, px: the eye row → the chin tip. */\n hh: number;\n /** Half the face plate's painted width on row `y`. */\n paintedHalfAt(y: number): number;\n /** The face plate's widest half-width. */\n wMax: number;\n /** The head's own widest half-width, its ears left out. */\n headMax: number;\n /** Whether the face carried a measured row profile. */\n hasProfile: boolean;\n /** The neck the face layer carries below its jaw, if any. */\n neck?: Neck;\n /** The ears it paints on its sides, if any. */\n ears?: Ears;\n /** The head's lower boundary at column x, model y: just under the jaw's\n * outline across the neck, just under the plate's own edge elsewhere.\n * What lies below it (the neck) stays with the body. */\n cutAt(x: number): number;\n /** The rows the plate's width change is read at. */\n cheekY: number;\n jawY: number;\n /** The held silhouette's edges at the eye row, model x. */\n shellLeft: number;\n shellRight: number;\n /** True when a measured head (hair) is wider than the face plate. */\n hairShell: boolean;\n /** The head half-width the turn cues are fractions of. */\n holdBase: number;\n /** A hair layer's opaque runs on the pixel row holding model y, as model x\n * boundaries `[start0, end0, start1, end1, …]` (its `rowRuns`); `[]` off\n * its crop, `undefined` when the layer is absent or carries none. */\n hairRuns(role: \"hair_front\" | \"hair_back\", y: number): number[] | undefined;\n /** The face's runs on model row `y`, as `hairRuns` answers them. */\n faceRuns(y: number): number[] | undefined;\n}\n\n/** The outermost edge of `runs` (model x boundaries) on `side` of the axis:\n * the last run's end on +x, the first run's start on −x; `undefined` when\n * no run reaches past the axis on that side. */\nexport function outerEdge(\n runs: number[],\n axisX: number,\n side: -1 | 1,\n): number | undefined {\n if (runs.length === 0) return undefined;\n const x = side > 0 ? runs[runs.length - 1] : runs[0];\n return side * (x - axisX) > 0 ? x : undefined;\n}\n\n/** How far the run of `runs` holding the pixel just inside boundary `x` on\n * `side` reaches inward of `x` and outward past it, px; 0 both where that\n * pixel is transparent. A run beyond a gap does not count. */\nexport function runReach(\n runs: number[],\n x: number,\n side: -1 | 1,\n): { inward: number; outward: number } {\n // The pixel just inside x: [x − 1, x) on +x, [x, x + 1) on −x.\n const px = side > 0 ? x - 1 : x;\n for (let k = 0; k < runs.length; k += 2) {\n const [a, b] = [runs[k], runs[k + 1]];\n if (a <= px && px + 1 <= b) {\n return side > 0\n ? { inward: x - a, outward: b - x }\n : { inward: b - x, outward: x - a };\n }\n }\n return { inward: 0, outward: 0 };\n}\n\n/** Rows filled in; `null` without a usable profile. */\nfunction filledProfile(rows: number[] | undefined): number[] | null {\n if (rows === undefined || !rows.some((v) => v > 0)) return null;\n const out = rows.slice();\n const first = out.findIndex((v) => v > 0);\n for (let i = 0; i < first; i++) out[i] = out[first];\n for (let i = first + 1; i < out.length; i++)\n if (!(out[i] > 0)) out[i] = out[i - 1];\n return out;\n}\n\n/** A light box filter: a stray pixel on the outline must not move the cut. */\nconst smoothProfile = (rows: number[]): number[] =>\n boxSmooth(rows, Math.max(1, Math.round(rows.length * 0.01)));\n\n/** Where an ear juts out: the outline steps out by EAR_STEP of the plate's\n * widest half-width within EAR_ROWS rows, and back in below. */\nconst EAR_STEP = 0.03;\nconst EAR_ROWS = 3;\n\n/**\n * An ear on the plate's outline: a step out, a band at least a tenth of the\n * eye→chin span tall, and a step back in, all above the chin. The head's own\n * outline under it is the line between the rows just outside the band.\n */\nfunction findEars(\n raw: number[],\n wMax: number,\n firstRow: number,\n lastRow: number,\n minRows: number,\n maxRows: number,\n): { top: number; bottom: number } | undefined {\n const step = Math.max(4, EAR_STEP * wMax);\n for (let t = Math.max(firstRow, EAR_ROWS); t < lastRow; t++) {\n if (raw[t] - raw[t - EAR_ROWS] < step) continue;\n for (let b = t + minRows; b <= Math.min(lastRow, t + maxRows); b++) {\n if (raw[b - EAR_ROWS] - raw[b] >= step) {\n return { top: t - EAR_ROWS, bottom: b };\n }\n }\n return undefined;\n }\n return undefined;\n}\n\nfunction boxSmooth(v: number[], k: number): number[] {\n return v.map((_, i) => {\n let s = 0;\n let n = 0;\n for (let j = i - k; j <= i + k; j++) {\n if (j < 0 || j >= v.length) continue;\n s += v[j];\n n++;\n }\n return s / n;\n });\n}\n\n/** How far under the jaw's outline the cut runs, px: the stroke's\n * antialiased fringe stays on the head. */\nconst CUT_MARGIN = 2;\n/** The cut takes the lowest of each column's neighbours this many columns\n * either side, and is read linearly between columns. On a jaw rising away\n * from the chin, that draws the cut's shape — the shade band's end among it\n * — up to one column more than that further out. */\nconst CUT_LOW = 3;\n/** How much of a depth under the jaw's line holds at offset d from the axis:\n * all of it under the chin, thinning evenly to none at the neck's outline,\n * where the outline's own first pixels lie. The cut's fringe margin thins\n * so, and the depth the neck's hidden rows sample the drawing at. */\nexport function fadeToOutline(d: number, nk: Neck): number {\n return Math.max(0, 1 - d / nk.waist);\n}\n\n/** A measured stroke is the jaw's only if it runs within STROKE_SLACK px of\n * the median of the STROKE_RUN columns either side of it. */\nconst STROKE_RUN = 4;\nconst STROKE_SLACK = 6;\n/** Under a measured jaw stroke, the dark band a chin casts on the neck goes\n * with the chin too (hh): left on the neck, it reads as a second jaw line\n * once the chin slides off it. It goes only as far as a full turn keeps it\n * on the neck: given the chin's slide at AngleX 30, the cut draws the\n * band's end no nearer the waist than that slide and a CUT_MARGIN, so at\n * ±30 the end lands at least 2 px inside the neck's outline. Carried\n * further, a turn slides it past the outline, an unlined wedge of neck over\n * the outline's top. */\nconst JAW_SHADE = 0.05;\n\nexport function buildHeadFrame(\n layers: LayerInput[],\n opts: {\n headHalfWidth?: number;\n headEdges?: HeadEdges;\n /** The chin's slide at AngleX 30, px. Without it the chin's shade band\n * reaches the neck's outline. */\n chinSlide?: number;\n },\n): HeadFrame {\n const byRole = new Map(layers.map((l) => [l.role, l]));\n const faceLayer = byRole.get(\"face\")!;\n const { canvasW, canvasH } = faceLayer;\n const face = boxOfLayer(faceLayer);\n const axisX = cx(face);\n const plateHalf = faceLayer.cropW / 2;\n\n const centreY = (role: string) => {\n const l = byRole.get(role);\n return l === undefined ? undefined : cy(boxOfLayer(l));\n };\n const pair = (a: string, b: string) => {\n const ya = centreY(a);\n const yb = centreY(b);\n return ya === undefined || yb === undefined ? undefined : (ya + yb) / 2;\n };\n const eyeY = pair(\"iris_L\", \"iris_R\") ?? pair(\"eye_L\", \"eye_R\")!;\n const mouthY = centreY(\"mouth\")!;\n\n // Model y of crop row r's centre, and of its lower boundary.\n const rowY = (r: number) => canvasH / 2 - (faceLayer.bbox.y + r + 0.5);\n const raw = filledProfile(faceLayer.rowHalfWidths);\n const profile = raw === null ? null : smoothProfile(raw);\n\n let wMax = plateHalf;\n let paintedHalfAt: (y: number) => number = () => plateHalf;\n let neck: Neck | undefined;\n let ears: Ears | undefined;\n let headMax = plateHalf;\n let chinY = face.y0;\n let cutAt: (x: number) => number = () => face.y0 - 1;\n\n if (profile !== null && raw !== null) {\n wMax = Math.max(...profile);\n headMax = wMax;\n let widestRow = 0;\n for (let r = 0; r < profile.length; r++) {\n if (profile[r] >= wMax - 0.5) widestRow = r;\n }\n const prof = profile;\n paintedHalfAt = (y: number) => {\n const r = canvasH / 2 - y - faceLayer.bbox.y - 0.5;\n const i = clamp(Math.floor(r), 0, prof.length - 1);\n const j = Math.min(i + 1, prof.length - 1);\n const t = clamp(r - i, 0, 1);\n return prof[i] + (prof[j] - prof[i]) * t;\n };\n\n // Ears, looked for between the plate's top fifth and the chin: the\n // plate's profile with their band replaced by the head's own outline\n // under them (a line between the rows just outside the band).\n const rawRows = raw;\n const earless = (chin: number): number[] => {\n const rowOf = (y: number) =>\n Math.round(canvasH / 2 - y - faceLayer.bbox.y - 0.5);\n const span = Math.max(1, eyeY - chin);\n const found = findEars(\n rawRows,\n wMax,\n Math.round(0.2 * rawRows.length),\n Math.min(rawRows.length - 1, rowOf(chin)),\n Math.round(0.1 * span),\n Math.round(0.8 * span),\n );\n if (found === undefined) return profile;\n const { top, bottom } = found;\n const a = rawRows[top];\n const b = rawRows[bottom];\n const attach = (r: number) =>\n a + ((b - a) * (r - top)) / Math.max(1, bottom - top);\n let outer = 0;\n for (let r = top; r <= bottom; r++) outer = Math.max(outer, rawRows[r]);\n ears = {\n top: rowY(top) + 0.5,\n bottom: rowY(bottom) - 0.5,\n attachAt: (y: number) =>\n attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)),\n outer,\n };\n return smoothProfile(\n rawRows.map((v, r) => (r > top && r < bottom ? attach(r) : v)),\n );\n };\n\n // A neck: below the jaw the plate settles onto a narrow plateau that\n // runs on for a while (the last few rows are the neck's own cut edge).\n const n = profile.length;\n const tail = Math.max(1, Math.floor(n * 0.05));\n let minW = Infinity;\n for (let r = widestRow; r < n - tail; r++)\n minW = Math.min(minW, profile[r]);\n if (Number.isFinite(minW) && minW < 0.7 * wMax) {\n const threshold = minW + 0.15 * (wMax - minW);\n let neckRow = -1;\n for (let r = widestRow + 1; r < n; r++) {\n if (profile[r] <= threshold) {\n neckRow = r;\n break;\n }\n }\n if (neckRow >= 0 && n - neckRow >= 0.12 * n) {\n let span = 0;\n let waist = Infinity;\n for (let r = neckRow; r < n; r++) {\n span = Math.max(span, profile[r]);\n if (r < n - tail) waist = Math.min(waist, profile[r]);\n }\n neck = {\n topY: rowY(neckRow),\n half: profile[neckRow],\n span,\n waist: Math.min(waist, profile[neckRow]),\n };\n }\n }\n\n if (neck !== undefined) {\n const nk = neck;\n // Where the measurer found the jaw's stroke, per crop column: model y\n // of its lower boundary — only inside the neck, and only between the\n // neck's top and its bottom (a dark mark anywhere else is not a jaw).\n const jaw = faceLayer.jawRows;\n const rawStroke = (i: number): number | undefined => {\n const row = jaw?.[i];\n if (row === undefined || row < 0) return undefined;\n const y = canvasH / 2 - (row + 1);\n return y <= nk.topY + 2 && y > face.y0 + 0.1 * (nk.topY - face.y0)\n ? y\n : undefined;\n };\n // A jaw line runs on from column to column: a stroke far off its\n // neighbours' is some other mark the scan met (a collar, a choker, a\n // column that slipped through the line's antialiasing), not the jaw.\n const strokes = Array.from({ length: faceLayer.cropW }, (_, i) =>\n rawStroke(i),\n );\n const strokeAt = (i: number): number | undefined => {\n const y = strokes[i];\n if (y === undefined) return undefined;\n const near: number[] = [];\n for (let j = i - STROKE_RUN; j <= i + STROKE_RUN; j++) {\n const v = strokes[j];\n if (j !== i && v !== undefined) near.push(v);\n }\n if (near.length < STROKE_RUN) return undefined;\n near.sort((a, b) => a - b);\n const median = near[near.length >> 1];\n return Math.abs(y - median) <= STROKE_SLACK ? y : undefined;\n };\n const colX = (i: number) => faceLayer.bbox.x + i + 0.5 - canvasW / 2;\n // The chin: the stroke's lowest point near the axis, or failing a\n // measured stroke the anime proportion — about half the eye→mouth span\n // under the mouth — kept between the neck's top and its bottom.\n let measuredChin = Infinity;\n for (let i = 0; i < faceLayer.cropW; i++) {\n if (Math.abs(colX(i) - axisX) > 0.35 * nk.half) continue;\n const y = strokeAt(i);\n if (y !== undefined) measuredChin = Math.min(measuredChin, y);\n }\n chinY = Number.isFinite(measuredChin)\n ? measuredChin\n : clamp(\n mouthY - 0.55 * (eyeY - mouthY),\n face.y0 + 0.4 * (nk.topY - face.y0),\n nk.topY,\n );\n // The jaw's own outline at a column offset d from the axis, off the\n // neck: the lowest row above the neck whose span, less any ear, reaches\n // it.\n const neckRow = Math.round(\n canvasH / 2 - nk.topY - faceLayer.bbox.y - 0.5,\n );\n const head = earless(chinY);\n headMax = Math.max(...head);\n const outlineAt = (d: number): number => {\n for (let r = neckRow; r >= 0; r--) {\n if (head[r] >= d) return rowY(r) - 0.5;\n }\n // A column wholly outside the head (past its ears' reach, say)\n // collapses to its top.\n return face.y1;\n };\n const chin = chinY;\n const shade = JAW_SHADE * Math.max(1, eyeY - chin);\n // Where the band thins to nothing: CUT_LOW + 1 columns short of the\n // furthest the cut may draw its end. Without a slide, at the neck's\n // outline.\n const reach =\n opts.chinSlide === undefined\n ? nk.waist\n : clamp(\n nk.waist - opts.chinSlide - CUT_MARGIN - (CUT_LOW + 1),\n 0,\n nk.waist,\n );\n // The furthest column the band reaches under a measured stroke.\n let banded = -1;\n const cut = new Float64Array(faceLayer.cropW);\n for (let i = 0; i < faceLayer.cropW; i++) {\n const d = Math.abs(colX(i) - axisX);\n // Across the neck, the jaw's measured stroke; without one, a V from\n // where the jaw meets the neck's sides down to the chin. Beside the\n // neck, the jaw's own outline (below it the layer is empty, save a\n // collar flare the neck keeps).\n const stroke = d <= nk.half ? strokeAt(i) : undefined;\n // The chin's shade goes with the head only across the neck's middle,\n // thinning to nothing at its reach (see JAW_SHADE). The stroke's\n // fringe margin thins on to the outline itself, where not even that\n // goes: the outline's own first pixels would go with it.\n const band = reach > 0 ? Math.max(0, 1 - d / reach) : 0;\n if (stroke !== undefined && band > 0) banded = Math.max(banded, d);\n const y =\n stroke !== undefined\n ? stroke - shade * band - CUT_MARGIN * fadeToOutline(d, nk)\n : (d <= nk.half\n ? chin + (nk.topY - chin) * (d / Math.max(1, nk.half))\n : outlineAt(d)) - CUT_MARGIN;\n // A column wholly outside the head stays collapsed onto its top.\n cut[i] = y >= face.y1 ? face.y1 : y;\n }\n // The lowest of each column's neighbours: a stroke that dips between\n // two sampled columns stays on the head.\n const low = cut.map((_, i) => {\n let m = Infinity;\n for (let j = i - CUT_LOW; j <= i + CUT_LOW; j++) {\n if (j >= 0 && j < cut.length) m = Math.min(m, cut[j]);\n }\n return m;\n });\n // Where the cut draws the band's end: CUT_LOW columns past the last\n // it reaches, then read toward the next.\n if (opts.chinSlide !== undefined && banded >= 0)\n nk.bandEnd = banded + CUT_LOW + 1;\n cutAt = (x: number) => {\n const f = x - (faceLayer.bbox.x - canvasW / 2) - 0.5;\n const i = clamp(Math.floor(f), 0, low.length - 1);\n const j = Math.min(i + 1, low.length - 1);\n const t = clamp(f - i, 0, 1);\n return Math.max(face.y0, low[i] + (low[j] - low[i]) * t);\n };\n } else {\n // No neck: the plate is all head, save its ears, which it ends beside.\n const head = earless(chinY);\n headMax = Math.max(...head);\n if (ears !== undefined) {\n const bottomOf = (d: number): number => {\n for (let r = head.length - 1; r >= 0; r--) {\n if (head[r] >= d) return rowY(r) - 0.5;\n }\n return face.y1;\n };\n cutAt = (x: number) => {\n const y = bottomOf(Math.abs(x - axisX));\n return y >= face.y1 ? face.y1 : Math.max(face.y0, y - CUT_MARGIN);\n };\n }\n }\n }\n\n const hh = Math.max(1, eyeY - chinY);\n\n const headHalf = opts.headHalfWidth;\n const hairShell = headHalf !== undefined;\n let shellLeft = axisX - plateHalf;\n let shellRight = axisX + plateHalf;\n if (hairShell) {\n if (\n opts.headEdges &&\n opts.headEdges.left.length > 0 &&\n opts.headEdges.right.length > 0\n ) {\n shellLeft = Math.min(...opts.headEdges.left.map((e) => e.x));\n // A right edge names its outermost pixel column; its outer boundary is\n // one pixel further.\n shellRight = Math.max(...opts.headEdges.right.map((e) => e.x)) + 1;\n } else {\n shellLeft = axisX - headHalf;\n shellRight = axisX + headHalf;\n }\n }\n\n const runsOf = (\n role: \"face\" | \"hair_front\" | \"hair_back\",\n y: number,\n ): number[] | undefined => {\n const l = byRole.get(role);\n if (l?.rowRuns === undefined) return undefined;\n const runs = l.rowRuns[Math.floor(canvasH / 2 - y) - l.bbox.y];\n return runs === undefined ? [] : runs.map((c) => c - canvasW / 2);\n };\n const hairRuns = (role: \"hair_front\" | \"hair_back\", y: number) =>\n runsOf(role, y);\n const faceRuns = (y: number) => runsOf(\"face\", y);\n\n return {\n canvasW,\n canvasH,\n face,\n axisX,\n eyeY,\n mouthY,\n chinY,\n hh,\n paintedHalfAt,\n wMax,\n headMax,\n hasProfile: profile !== null,\n neck,\n ears,\n cutAt,\n cheekY: eyeY - 0.5 * (eyeY - chinY),\n jawY: eyeY - 0.8 * (eyeY - chinY),\n shellLeft,\n shellRight,\n hairShell,\n holdBase: headHalf ?? plateHalf,\n hairRuns,\n faceRuns,\n };\n}\n","/**\n * The head's motion as one displacement field per family, read off the\n * profile (`profile.ts`). A turn is parallax: the plate translates,\n * each feature leads it by its own amount (and the eyes foreshorten about\n * their own centres), the front hair rides it, the back hair drifts slightly\n * against it, and the neck under the jaw does not move. A nod is the same,\n * vertically. Every field is linear in each parameter on each side of rest,\n * so the keyforms at 0 and ±30 carry it exactly, and a turn and a nod add.\n */\n\nimport type { Family } from \"./roles\";\nimport { clamp, cx, cy, DEG, smoothstep, type Box } from \"./layout\";\nimport { outerEdge, runReach, type HeadFrame } from \"./head\";\nimport { NOD, TURN } from \"./profile\";\n\nexport type Field = (\n x: number,\n y: number,\n ax: number,\n ay: number,\n) => [number, number];\n\ntype Side = { far: number; near: number };\ntype Nod = { up: number; down: number };\n\n/** Everything the fields need, in px (turn amounts along the turn at ±30). */\nexport interface TurnModel {\n frame: HeadFrame;\n /** The plate's translation, and the chin's lead over it. */\n face: number;\n chinLead: number;\n /** The plate's width at full turn, eye/cheek rows and jaw. */\n widthUpper: number;\n widthJaw: number;\n eye: Side;\n /** Each eye's width at full turn (far, near). */\n eyeScale: Side;\n brow: Side;\n nose: number;\n mouth: number;\n mouthWidth: number;\n /** The mouth's and the nose's tilts, as a share of the profile's. */\n tilt: number;\n hairFront: number;\n /** The front hair over the far eye: at least as far as that eye's outer\n * corner goes, so the lock over it keeps it no deeper than drawn. */\n hairFar: number;\n /** The front hair's outer edge — the head's outline where it draws it. */\n hairOuter: number;\n hairBack: number;\n /** The hair layers' width at full turn, about the axis (the silhouette). */\n shellScale: number;\n /** The far ear's width at full turn, about its outer edge. */\n earFarScale: number;\n /** Landmarks: each eye white's and brow's box, the nose's landmark and\n * bridge top, the mouth drawings' centre. */\n boxes: Partial<Record<\"eye_L\" | \"eye_R\" | \"brow_L\" | \"brow_R\", Box>>;\n noseAt?: { x: number; y: number };\n noseTopY?: number;\n mouthAt: { x: number; y: number };\n /** The front hair's top edge, model y. */\n hairTop: number;\n /** The front hair's mesh grid. The render interpolates linearly between\n * its vertices, so its outer edge's ride is bounded per vertex row. */\n hairFrontGrid?: HairFrontGrid;\n}\n\n/** The front hair's mesh grid, model coords: its vertex columns left to\n * right (even columns plus those where its follow bends), and its vertex\n * rows top to bottom, evenly spaced. */\nexport interface HairFrontGrid {\n xs: number[];\n ys: number[];\n}\n\n/** The nose's tip swings to the far side about its bridge top by this much\n * at a full turn: it stands further proud than its bridge. */\nexport const NOSE_TILT_DEG = 6;\n\n/** Screen-down hh at ±30 → model dy (y up), px. */\nfunction nodDy(v: Nod, ay: number, hh: number): number {\n const up = Math.max(0, ay) / 30;\n const down = Math.max(0, -ay) / 30;\n return -(up * v.up + down * v.down) * hh;\n}\n\n/** Rotate (px, py) about (ox, oy) by `a` radians, CCW; the displacement. */\nfunction spin(\n x: number,\n y: number,\n ox: number,\n oy: number,\n a: number,\n): [number, number] {\n if (a === 0) return [0, 0];\n const px = x - ox;\n const py = y - oy;\n return [\n px * Math.cos(a) - py * Math.sin(a) - px,\n px * Math.sin(a) + py * Math.cos(a) - py,\n ];\n}\n\n/** The head's own plate: a translation, the chin leading it, its width as\n * the profile and the fit give it. */\nexport function faceField(m: TurnModel): Field {\n const f = m.frame;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const chin = smoothstep(f.mouthY, f.chinY, y);\n const width =\n m.widthUpper +\n (m.widthJaw - m.widthUpper) * smoothstep(f.cheekY, f.jawY, y);\n // Without hair the plate is the silhouette, and the silhouette's own\n // width change is its.\n const shell = f.hairShell ? 0 : m.shellScale - 1;\n const dx =\n s * a * (m.face + m.chinLead * chin) +\n a * (width - 1 + shell) * (x - f.axisX);\n const t = Math.min(\n 1,\n Math.max(0, (f.face.y1 - y) / Math.max(1, f.face.y1 - f.chinY)),\n );\n const v = {\n up: NOD.faceTop.up + (NOD.chin.up - NOD.faceTop.up) * t,\n down: NOD.faceTop.down + (NOD.chin.down - NOD.faceTop.down) * t,\n };\n return [dx, nodDy(v, ay, f.hh)];\n };\n}\n\n/**\n * The ears the plate paints: on the head, but behind the face, so they lag\n * its slide, and nod with it. The far one's outer edge lags most, and the\n * ear narrows about it (to `earFarScale` of its width at a full turn, where\n * the head leaves it room): its root follows the head further, sliding a\n * little under the cheek, but never further than the head moves on the line\n * under the ear — so where the head leaves less room, it narrows less — and\n * its tucked strip no further than the head over it, so it stays covered. The\n * turn solve keeps the head moving at least as far on that line as the\n * ear's outer edge (`farEarCovered`), so the ear never widens. The near\n * one's root — what lies inside the head's own outline, tucked under it —\n * moves as the head moves it there, and the ear eases evenly out to its own\n * lag at its widest reach: it widens a little rather than sliding out from\n * under the head, so its tucked strip never shows.\n */\nexport function earField(m: TurnModel): Field {\n const f = m.frame;\n const ears = f.ears;\n if (ears === undefined) return () => [0, 0];\n const face = faceField(m);\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const dy = face(x, y, 0, ay)[1];\n const d = Math.abs(x - f.axisX);\n const attach = ears.attachAt(y);\n const span = Math.max(1, ears.outer - attach);\n if (sideOf(m, x, s) === \"far\") {\n const rim = TURN.earFar * m.face;\n // How much further than the rim the root goes at a full turn: as far\n // as the ear's narrowing takes it, but no further than the head there\n // — and where the head moves less than the rim, not at all: the ear\n // never widens.\n const root = earRoot(m, face, y, s);\n const lead = Math.max(\n 0,\n Math.min((1 - m.earFarScale) * span, root - rim),\n );\n let along = rim + (lead * (ears.outer - d)) / span;\n // The tucked strip, inside that line, no further than the head over\n // it: the narrowing's slope can outrun a head narrowing less there\n // (and should the head not cover the rim, this still keeps it).\n if (d < attach) along = Math.min(along, s * face(x, y, 30 * s, 0)[0]);\n return [s * a * along, dy];\n }\n if (d <= attach) return [face(x, y, ax, 0)[0], dy];\n const root = face(f.axisX + Math.sign(x - f.axisX) * attach, y, ax, 0)[0];\n const rim = s * a * TURN.earNear * m.face;\n const t = Math.min(1, (d - attach) / span);\n return [root + (rim - root) * t, dy];\n };\n}\n\n/** The head's motion along a full turn toward s on the line under the ears\n * at model y (the plate's `face` field), px. */\nfunction earRoot(m: TurnModel, face: Field, y: number, s: number): number {\n const f = m.frame;\n return s * face(f.axisX + s * f.ears!.attachAt(y), y, 30 * s, 0)[0];\n}\n\n/**\n * Whether the head covers the far ear's slide: on every row of the ear\n * islands (the band and the 2 px they run past it either way), the head\n * moves at least as far along a full turn, either way, on the line under the\n * ear as the far ear's outer edge does (`TURN.earFar` of the plate's slide).\n * True without ear islands.\n */\nexport function farEarCovered(m: TurnModel): boolean {\n const ears = m.frame.ears;\n if (ears === undefined) return true;\n const face = faceField(m);\n const rim = TURN.earFar * m.face;\n const y0 = ears.bottom - 2;\n const y1 = ears.top + 2;\n const n = Math.max(1, Math.ceil(y1 - y0));\n for (let i = 0; i <= n; i++) {\n const y = y0 + ((y1 - y0) * i) / n;\n for (const s of [-1, 1]) if (earRoot(m, face, y, s) < rim) return false;\n }\n return true;\n}\n\n/** How far the chin slides at a full turn, px. */\nexport function chinSlide(m: TurnModel): number {\n const f = m.frame;\n return Math.abs(faceField(m)(f.axisX, f.chinY, 30, 0)[0]);\n}\n\n/** How far the shade under the chin may slide across the neck, as a share of\n * the neck's half-width: its outline stays put, and the drawing between them\n * keeps more than half its width. */\nconst NECK_SHADE_MAX = 0.45;\n/** How far down from the chin's cut the shade still slides whole, as a share\n * of the neck below it. */\nconst NECK_SHADE_FULL = 0.2;\n\n/**\n * The neck the plate paints: still, its outline and its base on the\n * shoulders — but the shade the chin casts on it slides sideways with the\n * chin, most under the chin and not at all at the base, across and not over\n * its outline. (A nod needs none: looking down, the chin covers the shade;\n * looking up, it uncovers more of it, in the hidden top's shade.)\n */\nexport function neckField(m: TurnModel): Field {\n const f = m.frame;\n const nk = f.neck;\n if (nk === undefined) return () => [0, 0];\n const face = faceField(m);\n const full = chinSlide(m);\n const share = Math.min(1, (NECK_SHADE_MAX * nk.waist) / Math.max(1e-6, full));\n // By row only: from a little under the chin up it slides whole, fading to\n // nothing at the neck's base — the jaw's V and the neck's rows under it\n // make narrow cells, which a weight changing across them would fold.\n const bottom = f.face.y0;\n const tip = f.cutAt(f.axisX);\n const top = tip - NECK_SHADE_FULL * (tip - bottom);\n return (x, y, ax) => {\n const wy = Math.min(\n 1,\n Math.max(0, (y - bottom) / Math.max(1, top - bottom)),\n );\n const wx = Math.max(0, 1 - Math.abs(x - f.axisX) / nk.waist);\n return [share * face(f.axisX, f.chinY, ax, 0)[0] * wx * wy, 0];\n };\n}\n\nfunction sideOf(m: TurnModel, x: number, s: number): \"far\" | \"near\" {\n return s * (x - m.frame.axisX) > 0 ? \"far\" : \"near\";\n}\n\nfunction eyeField(m: TurnModel, box: Box): Field {\n const xe = cx(box);\n const ye = cy(box);\n const hh = m.frame.hh;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const side = sideOf(m, xe, s);\n const dx = s * a * m.eye[side] + a * (m.eyeScale[side] - 1) * (x - xe);\n const up = Math.max(0, ay) / 30;\n const down = Math.max(0, -ay) / 30;\n const squash =\n up * (NOD.eyeHeight.up - 1) + down * (NOD.eyeHeight.down - 1);\n return [dx, nodDy(NOD.eye, ay, hh) + squash * (y - ye)];\n };\n}\n\nfunction browField(m: TurnModel, box: Box): Field {\n const xb = cx(box);\n return (_x, _y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n return [s * a * m.brow[sideOf(m, xb, s)], nodDy(NOD.brow, ay, m.frame.hh)];\n };\n}\n\nfunction noseField(m: TurnModel): Field {\n const at = m.noseAt!;\n const top = m.noseTopY ?? at.y;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n // The tip swings toward the far side: a CCW turn of a point below the\n // bridge top moves it toward +x.\n const [tx, ty] = spin(\n x,\n y,\n at.x,\n top,\n s * a * m.tilt * NOSE_TILT_DEG * DEG,\n );\n return [s * a * m.nose + tx, nodDy(NOD.nose, ay, m.frame.hh) + ty];\n };\n}\n\nfunction mouthField(m: TurnModel): Field {\n const c = m.mouthAt;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n // Narrower about its centre, then the far corner up: a CCW turn lifts\n // the +x corner, which is the far one turning toward +x.\n const wx = c.x + (x - c.x) * (1 + a * (m.mouthWidth - 1));\n const [tx, ty] = spin(\n wx,\n y,\n c.x,\n c.y,\n s * a * m.tilt * TURN.mouthTiltDeg * DEG,\n );\n return [\n s * a * m.mouth + wx - x + tx,\n nodDy(NOD.mouth, ay, m.frame.hh) + ty,\n ];\n };\n}\n\nfunction hairField(m: TurnModel, shift: number, nod: Nod): Field {\n const f = m.frame;\n return (x, _y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n return [\n s * a * shift + a * (m.shellScale - 1) * (x - f.axisX),\n nodDy(nod, ay, f.hh),\n ];\n };\n}\n\n/**\n * Where the front hair's follow bends, as offsets from the axis: it rides the\n * face whole out to the eyes' outer corners (`inner`), then eases evenly to\n * the outline's own follow at the outline on each side (`left`, `right`) —\n * spread over all of that width, since on the far side the lock is squeezed\n * by as much as the face out-turns the outline. The hair's mesh has columns\n * here, so it carries the bends exactly.\n */\nexport function hairFrontBends(\n frame: HeadFrame,\n boxes: TurnModel[\"boxes\"],\n): { inner: number; left: number; right: number } {\n const f = frame;\n const eyes = [boxes.eye_L, boxes.eye_R].filter(\n (e): e is Box => e !== undefined,\n );\n const inner = Math.max(\n 1,\n Math.min(\n f.paintedHalfAt(f.eyeY),\n ...eyes.map((e) => Math.max(f.axisX - e.x0, e.x1 - f.axisX)),\n ),\n );\n return {\n inner,\n left: Math.max(inner + 1, f.axisX - f.shellLeft),\n right: Math.max(inner + 1, f.shellRight - f.axisX),\n };\n}\n\n/**\n * The front hair: over the face its bangs and the inner parts of its side\n * locks ride the face (and over the far eye, as far as that eye's corner\n * goes); out at the head's outline its outer edge follows only as far as\n * `hairOuter` — the outline is the back hair's, and holds —\n * the lock easing between. On a row where the back hair paints behind that\n * edge at every turn and nod angle, the edge rides further, up to the face's\n * follow, and on its cap less, so that the turn never carries the edge\n * further outside the back hair painted behind it than the nod alone does\n * (`outerRide`). Its crown, above the face plate's top, is the top of the\n * head: on the turn it rides with the cap as far as back hair is painted\n * behind its edges and gaps at every turn and nod angle, never baring the\n * face, and no row further than the one under it (`crownRide`); elsewhere it\n * eases toward its top to the back hair's motion, so the head's top outline\n * holds while the fringe slides under it. On the nod it eases to its cap\n * top's — one slide for the whole cap (`capSlide`), so the cap moves with the\n * face rather than its bangs stretching from a pinned top.\n */\nfunction hairFrontField(m: TurnModel): Field {\n const f = m.frame;\n const back = hairField(m, m.hairBack, NOD.hairBack);\n const cap = { up: NOD.hairFrontTop.up, down: capSlide(m) };\n // The rows the far eye's own lead reaches: its box, easing out over one\n // eye height above and below (the lock bends there, not over its length).\n const eyes = [m.boxes.eye_L, m.boxes.eye_R].filter(\n (e): e is Box => e !== undefined,\n );\n const { inner, left, right } = hairFrontBends(f, m.boxes);\n const eyeY =\n eyes.length > 0\n ? eyes.reduce((t, e) => t + cy(e), 0) / eyes.length\n : f.eyeY;\n const eyeH =\n eyes.length > 0\n ? eyes.reduce((t, e) => t + (e.y1 - e.y0), 0) / eyes.length\n : 1;\n // Turning toward s: from the near side's follow to the far eye's across\n // the face (on the eye's rows) ...\n const coreAt = (x: number, y: number, s: number) => {\n const u = s * (x - f.axisX);\n const across = Math.min(1, Math.max(0, (u + inner) / (2 * inner)));\n const band = 1 - smoothstep(eyeH / 2, 1.5 * eyeH, Math.abs(y - eyeY));\n return m.hairFront + (m.hairFar - m.hairFront) * across * band;\n };\n // ... then out to the outline's.\n const followAt = (x: number, y: number, s: number) => {\n const core = coreAt(x, y, s);\n const out = Math.min(\n 1,\n Math.max(\n 0,\n (Math.abs(x - f.axisX) - inner) /\n ((x < f.axisX ? left : right) - inner),\n ),\n );\n return core + (m.hairOuter - core) * out;\n };\n // The cap: the rows above the eyes and off the far eye's band.\n const ride = outerRide(m, inner, coreAt, followAt, eyeY + 1.5 * eyeH);\n const followOf = (x: number, y: number, s: number) =>\n followAt(x, y, s) + (ride === undefined ? 0 : ride.lift(x, y, s));\n // The front hair's own motion against the back hair's, along the turn.\n const drift = Math.abs(m.hairBack);\n const crown = crownRide(m, cap, (x, y, s) => followOf(x, y, s) + drift);\n // On the cap the follow gives up its local cut, then blends toward the\n // back hair's own motion (a follow of −drift).\n const boundOf = (x: number, y: number, s: number) => {\n if (ride === undefined) return followOf(x, y, s);\n const b = ride.blend(y, s);\n return (1 - b) * (followOf(x, y, s) + ride.cut(x, y, s)) - b * drift;\n };\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const rx =\n s * a * boundOf(x, y, s) + a * (m.shellScale - 1) * (x - f.axisX);\n const ry = nodDy(NOD.hairFront, ay, f.hh);\n const bx = back(x, y, ax, ay)[0];\n const by = nodDy(cap, ay, f.hh);\n const w = crownBlend(m, y);\n const wx = crown === undefined ? w : w + crown(y, s);\n return [bx + wx * (rx - bx), by + w * (ry - by)];\n };\n}\n\n/** The share of the front hair's own motion at model y, the rest its\n * crown's (on the turn, before `crownRide`'s extra): all of it up to the\n * face plate's top, none at the hair's top. */\nfunction crownBlend(m: TurnModel, y: number): number {\n const top = m.frame.face.y1;\n return 1 - smoothstep(top, Math.max(top + 1, m.hairTop), y);\n}\n\n/** Where model y falls among the evenly spaced vertex rows `ys` (top to\n * bottom), as the render interpolates between them: the row above it, `r`,\n * and its share `t` of the way to the next. With `snap`, a vertex — whose y\n * the mesh rounds to 1e-5 of its box — reads its own row alone. */\nfunction gridRow(\n ys: number[],\n y: number,\n snap = false,\n): { r: number; t: number } {\n const n = ys.length;\n let v = clamp(((ys[0] - y) / (ys[0] - ys[n - 1])) * (n - 1), 0, n - 1);\n if (snap && Math.abs(v - Math.round(v)) < 1e-3) v = Math.round(v);\n const r = Math.min(n - 2, Math.floor(v));\n return { r, t: v - r };\n}\n\n/** Where model x falls among the vertex columns `xs` (left to right): the\n * cell's left column, `c`, and its share `t` of the way across it. */\nfunction gridCol(xs: number[], x: number): { c: number; t: number } {\n let c = 0;\n while (c < xs.length - 2 && xs[c + 1] < x) c++;\n return { c, t: clamp((x - xs[c]) / (xs[c + 1] - xs[c]), 0, 1) };\n}\n\n/** The pixel rows, [first, end), indexed from the hair's top `ys[0]`, that\n * overlap the cells either side of vertex row r — none at or past `limit`. */\nfunction rowWindow(ys: number[], r: number, limit: number): [number, number] {\n const n = ys.length;\n return [\n Math.max(0, Math.floor(ys[0] - ys[Math.max(0, r - 1)])),\n Math.min(limit, Math.ceil(ys[0] - ys[Math.min(n - 1, r + 1)])),\n ];\n}\n\n/** The crown's blend at each of the front hair's vertex rows `ys` (top to\n * bottom), and between them as the render interpolates it. */\nfunction renderedCrownBlend(\n m: TurnModel,\n ys: number[],\n): { wr: number[]; blendAt: (y: number) => number } {\n const wr = ys.map((y) => crownBlend(m, y));\n return {\n wr,\n blendAt: (y) => {\n const { r, t } = gridRow(ys, y);\n return wr[r] + (wr[r + 1] - wr[r]) * t;\n },\n };\n}\n\n/** The most back-hair cover, hh, a crown column may lose at its top when the\n * cap's top slides looking down, beyond what it loses at the back hair's\n * own nod (the slide without runs): a pixel or two, so the slide opens no\n * notch in the head's top. The rest of the cap's slide is the art's to\n * earn, with a back hair drawn up past the front hair's top. */\nconst CAP_COVER_LOSS = 0.01;\n\n/**\n * How far the front hair's cap top slides looking down, hh at −30: one value\n * for the whole cap, the largest up to `NOD.hairFrontTop.down` at which no\n * crown column loses more than `CAP_COVER_LOSS` of back-hair cover beyond\n * what it loses at the back hair's own nod (`least`). Without both hair\n * layers' runs it is that nod.\n *\n * A column's top, its first opaque row, drops by the crown's blend of the\n * bangs' nod and the slide there, read between the mesh's vertex rows as the\n * render interpolates it (in the crown the drop depends on the row alone, so\n * across vertex columns it adds nothing). The pixel rows whose centres it\n * uncovers show the back hair at its own posed place, its nod lower, or\n * nothing; the cost is how many more show nothing than at `least`. It never\n * falls as the slide grows, so bisection finds the largest.\n */\nfunction capSlide(m: TurnModel): number {\n const f = m.frame;\n const least = NOD.hairBack.down;\n const grid = m.hairFrontGrid;\n if (\n grid === undefined ||\n f.hairRuns(\"hair_front\", grid.ys[0]) === undefined ||\n f.hairRuns(\"hair_back\", grid.ys[0]) === undefined\n ) {\n return least;\n }\n const { xs, ys } = grid;\n const top = ys[0];\n const n = ys.length;\n const bangs = NOD.hairFront.down;\n const { wr, blendAt } = renderedCrownBlend(m, ys);\n // From the first vertex row whose blend is 1 down, the slide moves nothing.\n const flat = ys[wr.findIndex((w) => w >= 1)] ?? ys[n - 1];\n // Each pixel column's top, in pixel rows under the hair's top: the first\n // row above `flat` that paints it.\n const x0 = xs[0];\n const tops = new Float64Array(Math.round(xs[xs.length - 1] - x0)).fill(NaN);\n for (let i = 0; i < top - flat; i++) {\n const runs = f.hairRuns(\"hair_front\", top - i - 0.5)!;\n for (let k = 0; k < runs.length; k += 2) {\n for (let px = runs[k]; px < runs[k + 1]; px++) {\n const j = Math.round(px - x0);\n if (Number.isNaN(tops[j])) tops[j] = i;\n }\n }\n }\n // The pixel rows under a column's top whose centres a drop of s px bares,\n // up to the most either nod, the bangs' or the cap top's, drops it.\n const hh = f.hh;\n const most = Math.ceil(Math.max(bangs, NOD.hairFrontTop.down) * hh);\n const bared = (s: number) => clamp(Math.ceil(s - 0.5), 0, most);\n const dropAt = (w: number, slide: number) =>\n (w * bangs + (1 - w) * slide) * hh;\n // Per crown column: its blend, how many of the first r rows under its top\n // the posed back hair leaves empty (`empty[r]`), and that at `least`.\n const backNod = NOD.hairBack.down * hh;\n const backRows = new Map<number, number[]>();\n const columns: { w: number; empty: Int32Array; base: number }[] = [];\n tops.forEach((i, j) => {\n if (Number.isNaN(i)) return;\n const w = blendAt(top - i);\n const empty = new Int32Array(most + 1);\n for (let r = 0; r < most; r++) {\n // The back hair's own pixel row behind that row's centre, its nod up.\n const at = Math.floor(i + r + 0.5 - backNod);\n let runs = backRows.get(at);\n if (runs === undefined) {\n runs = f.hairRuns(\"hair_back\", top - at - 0.5)!;\n backRows.set(at, runs);\n }\n empty[r + 1] = empty[r] + (paints(runs, x0 + j) ? 0 : 1);\n }\n columns.push({ w, empty, base: empty[bared(dropAt(w, least))] });\n });\n const budget = CAP_COVER_LOSS * hh;\n const fits = (slide: number) =>\n columns.every((c) => c.empty[bared(dropAt(c.w, slide))] - c.base <= budget);\n let lo: number = least;\n let hi: number = NOD.hairFrontTop.down;\n if (fits(hi)) return hi;\n // `least` always fits (it costs nothing); 30 halvings leave the slide far\n // finer than a keyform's rounding.\n for (let k = 0; k < 30; k++) {\n const mid = (lo + hi) / 2;\n if (fits(mid)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n\n/** Whether `runs` (model x boundaries) paint the pixel column starting at\n * model x `px`. */\nfunction paints(runs: number[], px: number): boolean {\n for (let k = 0; k < runs.length; k += 2) {\n if (runs[k] <= px && px + 1 <= runs[k + 1]) return true;\n }\n return false;\n}\n\ntype Follow = (x: number, y: number, s: number) => number;\n\n/** The front hair's outer edge against the back hair behind it, on the\n * turn (see `outerRide`). */\ninterface OuterRide {\n /** How much further than `followAt` the edge rides. */\n lift: Follow;\n /** On the cap, the follow a row gives up out toward its edge (≤ 0). */\n cut: Follow;\n /** On the cap, the share of a row's follow that blends toward the back\n * hair's own motion. */\n blend: (y: number, s: number) => number;\n}\n\n/** A bound edge of the cap, as a vertex row bounds it: its side, its own\n * column, the column the render reads the row at for it, and how far its\n * back hair's run reaches past it and inside it, the least over the nod. */\ninterface CapEdge {\n side: -1 | 1;\n x: number;\n at: number;\n outward: number;\n inward: number;\n}\n\n/**\n * The front hair's outer edge against the back hair painted behind it, at\n * (x, y) turning toward s; `undefined` unless both hair layers carry runs.\n *\n * On a pixel row, take the back hair's run holding the front's outermost\n * pixel on a side, on each back row the row passes over on the nod, read at\n * the edge's rest column: `c_in` the least it reaches inside the edge,\n * `c_out` the least past it (both 0 where the back hair is transparent there\n * on any of them, or where the edge rises above the back hair's top looking\n * up). Both layers take the shell's width term, and the back hair drifts\n * against the turn by |hairBack|; above the chin both roll rigidly with the\n * head, so the roll changes nothing between them.\n *\n * `lift`: how much further than `followAt` the edge rides where the back\n * hair stays behind it. On the far side the edge goes out, and stays over\n * that run's outer end while its follow is at most shellScale·c_out − drift;\n * on the near side it comes in, and the strip it leaves is that run while\n * its follow is at most shellScale·c_in − drift. The full turn binds both,\n * and the face's follow caps them. The render interpolates linearly between\n * the mesh's vertices, so each vertex row takes the smallest allowance among\n * the pixel rows within one row interval either side, and the innermost of\n * their edges: its ride is what the allowance leaves over today's follow\n * there, ramped from 0 at the eyes' outer corners (`inner`) to 1 at that\n * edge, and 1 beyond — a linear interpolation of that concave ramp never\n * exceeds it. A vertex row whose edges nothing covers rides nothing more:\n * today's hold.\n *\n * `cut` and `blend`: on its cap — the cells whose two vertex rows both lie\n * at or above `capLimit`, above the eyes and off the far eye's band — the\n * turn puts the edge no further outside the back hair than the nod alone\n * puts it. A cap row and side is bound where the back hair at rest paints\n * the pixel just inside the edge; elsewhere the front draws the outline\n * itself, and nothing bounds it. A bound edge moves against the back hair by\n * w × (its follow + drift), w the crown's blend at the vertex row (0 bounds\n * nothing), so its follow must lie in [−shellScale·c_back ÷ w − drift,\n * shellScale·c_fwd ÷ w − drift]: c_fwd the reach the way it moves against\n * the back hair (c_out turning toward its side, c_in away), c_back the\n * other. Where a reach is 0 the nod alone already shows the edge outside, so\n * the turn may add nothing; the back hair's own motion, a follow of −drift,\n * lies in every interval. The render reads a vertex row for a point between\n * rows at one column of the point's cell (its TL→BR split): at or toward −x\n * of the point on the row above, toward +x on the row below — inside the\n * edge on the row above and outside it on the row below on the +x side, the\n * reverse on −x — so each vertex row holds each bound edge in its window\n * where the render reads it there.\n *\n * On a cap row at or below the plate's top, where today's follow exceeds an\n * interval's upper end, the row first gives up a local cut: growing cell by\n * cell from the axis's cell out to the first vertex column at or past the\n * outermost bound edge in its window, constant beyond, each cell taking a\n * share proportional to a quarter of its width at a full turn (of its rest\n * width where the turn widens it), scaled to the least that meets every\n * bound edge and never past that quarter: no cell narrows below 3/4 of\n * today's width. Then each row blends toward the back hair's motion by the\n * least share that brings every bound edge in its window, on both sides,\n * inside its interval — on a crown row, the whole bound — and going up from\n * the plate's top no crown row blends less than the one under it. Both are\n * linear between vertex columns, so the render carries them. `crownRide`\n * still reads today's follow (`followAt` + `lift`), so its extra weight is\n * today's; the cut and the blend only lower the motion along the turn, so\n * its own bound still holds where that weight rides.\n *\n * So at every angle of the turn, the nod and the roll the cap's edge goes no\n * further outside the back hair than the nod alone puts it. Below the cap\n * the front hair keeps today's motion, so the lock over the far eye still\n * goes as far as that eye's corner and the turn solve's far-iris bound is\n * untouched; and the sway springs, which swing each layer by its own height,\n * are bounded by nothing.\n */\nfunction outerRide(\n m: TurnModel,\n inner: number,\n coreAt: Follow,\n followAt: Follow,\n capLimit: number,\n): OuterRide | undefined {\n const f = m.frame;\n const grid = m.hairFrontGrid;\n if (grid === undefined) return undefined;\n const { xs, ys } = grid;\n const top = ys[0];\n // Both layers must carry runs: `hairRuns` answers undefined on every row\n // of a layer without them, so any row tells.\n if (\n f.hairRuns(\"hair_front\", top) === undefined ||\n f.hairRuns(\"hair_back\", top) === undefined\n ) {\n return undefined;\n }\n const drift = Math.abs(m.hairBack);\n const sides = [-1, 1] as const;\n const n = ys.length;\n const count = Math.round(top - ys[n - 1]);\n // The cap's last vertex row (0: no cap), and its pixel rows: those whose\n // centres lie on or above that row.\n let last = 0;\n while (last + 1 < n && ys[last + 1] >= capLimit) last++;\n const capRows =\n last === 0 ? 0 : Math.min(count, Math.floor(top - ys[last] - 0.5) + 1);\n // On the nod a front row passes over the back hair's rows: down by the\n // bangs' nod less the back hair's looking down, up by theirs looking up\n // (the crown, easing to the cap's smaller nod, passes over fewer). The\n // back's pixel rows, indexed as the front's from its top, from `j0`.\n const below = (NOD.hairFront.down - NOD.hairBack.down) * f.hh;\n const above = (NOD.hairBack.up - NOD.hairFront.up) * f.hh;\n const j0 = Math.floor(-above);\n const backRows = Array.from(\n { length: Math.ceil(count + below) - j0 },\n (_, j) => f.hairRuns(\"hair_back\", top - (j + j0) - 0.5)!,\n );\n // Per pixel row of the front hair's crop and side (−x, +x): the edge's\n // offset from the axis (NaN without one there), its back hair's least\n // reaches past it and inside it, and on the cap whether it is bound.\n const offset = sides.map(() => new Float64Array(count).fill(NaN));\n const reachOut = sides.map(() => new Float64Array(count));\n const reachIn = sides.map(() => new Float64Array(count));\n const bound = sides.map(() => new Uint8Array(count));\n for (let i = 0; i < count; i++) {\n const y = top - i - 0.5;\n const front = f.hairRuns(\"hair_front\", y)!;\n sides.forEach((side, k) => {\n const edge = outerEdge(front, f.axisX, side);\n if (edge === undefined) return;\n // The least reach over every back row the row's span overlaps at some\n // nod: a turn and a nod add.\n let outward = Infinity;\n let inward = Infinity;\n for (let j = Math.floor(i - above); j < Math.ceil(i + 1 + below); j++) {\n const c = runReach(backRows[j - j0], edge, side);\n outward = Math.min(outward, c.outward);\n inward = Math.min(inward, c.inward);\n }\n offset[k][i] = side * (edge - f.axisX);\n reachOut[k][i] = outward;\n reachIn[k][i] = inward;\n if (i < capRows && runReach(backRows[i - j0], edge, side).inward > 0)\n bound[k][i] = 1;\n });\n }\n // Per vertex row and side: the innermost edge in its window, and the ride\n // turning toward −x and toward +x.\n const end = new Float64Array(n * 2);\n const lift = new Float64Array(n * 4);\n for (let r = 0; r < n; r++) {\n const [i0, i1] = rowWindow(ys, r, count);\n sides.forEach((side, k) => {\n let d = Infinity;\n let outward = Infinity;\n let inward = Infinity;\n for (let i = i0; i < i1; i++) {\n if (Number.isNaN(offset[k][i])) continue;\n d = Math.min(d, offset[k][i]);\n outward = Math.min(outward, reachOut[k][i]);\n inward = Math.min(inward, reachIn[k][i]);\n }\n end[r * 2 + k] = d;\n if (d === Infinity || d <= inner) return;\n const x = f.axisX + side * d;\n sides.forEach((s, j) => {\n const allow = Math.min(\n coreAt(x, ys[r], s),\n m.shellScale * (s === side ? outward : inward) - drift,\n );\n lift[(r * 2 + k) * 2 + j] = Math.max(0, allow - followAt(x, ys[r], s));\n });\n });\n }\n const rowRide = (r: number, k: number, j: number, d: number) => {\n const v = lift[(r * 2 + k) * 2 + j];\n return v === 0\n ? 0\n : v * Math.min(1, (d - inner) / (end[r * 2 + k] - inner));\n };\n const liftAt: Follow = (x, y, s) => {\n const d = Math.abs(x - f.axisX);\n if (s === 0 || d <= inner) return 0;\n const k = x < f.axisX ? 0 : 1;\n const j = s < 0 ? 0 : 1;\n // Between vertex rows, as the render interpolates; a vertex reads its\n // own row's ride alone.\n const { r, t } = gridRow(ys, y, true);\n return rowRide(r, k, j, d) * (1 - t) + rowRide(r + 1, k, j, d) * t;\n };\n\n // --- the cap ---\n const nc = xs.length;\n /** Linear between vertex columns, as the render reads a row's values. */\n const along = (v: ArrayLike<number>, x: number) => {\n const { c, t } = gridCol(xs, x);\n return v[c] + (v[c + 1] - v[c]) * t;\n };\n /** Where the render reads vertex row r for the point (x, y), within x's\n * cell: at or toward −x of x in the cell under r, toward +x in the cell\n * above it; undefined where r has no weight there. */\n const readAt = (r: number, x: number, y: number): number | undefined => {\n const { c, t: fx } = gridCol(xs, x);\n const dx = xs[c + 1] - xs[c];\n if (r + 1 < n && y <= ys[r] && y >= ys[r + 1]) {\n const fy = (ys[r] - y) / (ys[r] - ys[r + 1]);\n if (fy >= 1) return undefined;\n return fx <= fy ? xs[c] : xs[c] + ((fx - fy) / (1 - fy)) * dx;\n }\n if (r > 0 && y > ys[r] && y < ys[r - 1]) {\n const fy = (ys[r - 1] - y) / (ys[r - 1] - ys[r]);\n return fx <= fy ? xs[c] + (fx / fy) * dx : xs[c + 1];\n }\n return undefined;\n };\n // Turning toward s a bound edge moves against the back hair toward s: out\n // past its run on the side it turns toward, in on the other. Its reach\n // that way, and the other.\n const ahead = (e: CapEdge, s: number) =>\n s === e.side ? e.outward : e.inward;\n const behind = (e: CapEdge, s: number) =>\n s === e.side ? e.inward : e.outward;\n /**\n * The local cut on vertex row r turning toward s, on `side` (its bound\n * edges `mine`; `today` the row's follow at each vertex column): each\n * cell's quarter of its width at a full turn (of its rest width where the\n * turn widens it), summed cell by cell from the axis's cell out to the\n * first vertex column at or past the outermost of those edges, constant\n * beyond, and scaled to the least that brings every edge to its interval's\n * upper end, never past that quarter. Per vertex column; 0 on the other\n * side.\n */\n const capCut = (\n r: number,\n s: number,\n side: -1 | 1,\n today: number[],\n mine: CapEdge[],\n ): Float64Array => {\n const reach = Math.max(...mine.map((e) => side * (e.x - f.axisX)));\n const quarter = new Float64Array(nc);\n const cols = xs\n .map((_, c) => c)\n .filter((c) => (xs[c] < f.axisX ? -1 : 1) === side);\n if (side < 0) cols.reverse();\n let total = 0;\n let x0 = f.axisX;\n let d0 = s * followAt(f.axisX, ys[r], s);\n let open = true;\n for (const c of cols) {\n if (open) {\n const d = (m.shellScale - 1) * (xs[c] - f.axisX) + s * today[c];\n const rest = side * (xs[c] - x0);\n const full = rest + side * (d - d0);\n total += Math.max(0, Math.min(full, rest)) / 4;\n x0 = xs[c];\n d0 = d;\n open = side * (xs[c] - f.axisX) < reach;\n }\n quarter[c] = total;\n }\n let scale = 0;\n for (const e of mine) {\n const need = along(today, e.at) - (m.shellScale * ahead(e, s) - drift);\n if (need <= 0) continue;\n const q = along(quarter, e.at);\n scale = Math.max(scale, q > 0 ? need / q : 1);\n }\n scale = Math.min(1, scale);\n return quarter.map((q) => scale * q);\n };\n // Per vertex row and direction: the cut at each vertex column, and the\n // blend.\n const cuts = new Float64Array(n * 2 * nc);\n const blend = new Float64Array(n * 2);\n const wr = ys.map((y) => crownBlend(m, y));\n for (let r = 0; r <= last && capRows > 0; r++) {\n const w = wr[r];\n if (w <= 0) continue;\n // The bound edges in the row's window, each where the render reads the\n // row for it.\n const edges: CapEdge[] = [];\n const [i0, i1] = rowWindow(ys, r, capRows);\n for (let i = i0; i < i1; i++) {\n sides.forEach((side, k) => {\n if (bound[k][i] === 0) return;\n const x = f.axisX + side * offset[k][i];\n const at = readAt(r, x, top - i - 0.5);\n if (at === undefined) return;\n edges.push({\n side,\n x,\n at,\n outward: reachOut[k][i],\n inward: reachIn[k][i],\n });\n });\n }\n if (edges.length === 0) continue;\n sides.forEach((s, j) => {\n // Today's follow at each vertex column, and after the cut.\n const today = xs.map((x) => followAt(x, ys[r], s) + liftAt(x, ys[r], s));\n const after = today.slice();\n if (w >= 1) {\n for (const side of sides) {\n const mine = edges.filter((e) => e.side === side);\n if (mine.length === 0) continue;\n const cut = capCut(r, s, side, today, mine);\n for (let c = 0; c < nc; c++) after[c] -= cut[c];\n }\n }\n let b = 0;\n for (const e of edges) {\n const rel = w * (along(after, e.at) + drift);\n const hi = m.shellScale * ahead(e, s);\n const lo = -m.shellScale * behind(e, s);\n if (rel > hi) b = Math.max(b, 1 - hi / rel);\n else if (rel < lo) b = Math.max(b, 1 - lo / rel);\n }\n blend[r * 2 + j] = b;\n for (let c = 0; c < nc; c++)\n cuts[(r * 2 + j) * nc + c] = after[c] - today[c];\n });\n }\n // Up from the plate's top, no crown row blends less than the one under it.\n for (let j = 0; j < 2; j++) {\n for (let r = n - 2; r >= 0; r--) {\n if (wr[r] < 1)\n blend[r * 2 + j] = Math.max(blend[r * 2 + j], blend[(r + 1) * 2 + j]);\n }\n }\n const cutRow = (r: number, j: number, x: number) =>\n r > last\n ? 0\n : along(cuts.subarray((r * 2 + j) * nc, (r * 2 + j + 1) * nc), x);\n return {\n lift: liftAt,\n // Between vertex rows, as the render interpolates; a vertex reads its own\n // row's alone.\n cut: (x, y, s) => {\n if (s === 0) return 0;\n const j = s < 0 ? 0 : 1;\n const { r, t } = gridRow(ys, y, true);\n return cutRow(r, j, x) * (1 - t) + cutRow(r + 1, j, x) * t;\n },\n blend: (y, s) => {\n if (s === 0) return 0;\n const j = s < 0 ? 0 : 1;\n const { r, t } = gridRow(ys, y, true);\n return blend[r * 2 + j] * (1 - t) + blend[(r + 1) * 2 + j] * t;\n },\n };\n}\n\n/**\n * How much of the front hair's own motion the crown takes on the turn at\n * model y turning toward s, beyond `crownBlend`'s; `undefined` unless both\n * hair layers carry runs.\n *\n * Eased to the back hair's motion, the crown uncovers nothing new. Riding\n * further, each of its boundaries moves against the back hair, and must\n * uncover no background and no skin, at any angle of the turn and the nod.\n * On a pixel row, the far outer edge goes out, and must stay over the back's\n * run past it (`c_out`); every trailing boundary — a run's start turning\n * toward +x, its end toward −x: each gap's sides and the near outer edge —\n * leaves a strip the back's run inside it must fill (`c_in`). Each reach is\n * the least over the back rows the row passes over on its own nod (the\n * crown's rendered blend of the bangs' nod and the cap top's, less the back\n * hair's), and both layers take the shell's width term. The face lies in\n * front of the back hair: a trailing strip that meets a face run at the same\n * angle of the turn, on a face row it passes over on the nod relative to the\n * face, would bare skin, so nothing backs it.\n *\n * The render mixes vertex values with non-negative weights, so a boundary\n * moves against the back hair at most R × the rendered weight there, R the\n * largest motion against it (`relAt`) of the four vertices of its cell. Each\n * crown vertex row therefore takes the least allowance ÷ R − today's rendered\n * blend over the pixel rows within one row interval either side, between 0\n * and what brings it to the front hair's own motion: each boundary moves at\n * most today's motion plus its slack. An R of 0 bounds nothing. Then, up from\n * the plate's top, no row rides further than the one under it, so the cap's\n * outline does not shear.\n */\nfunction crownRide(\n m: TurnModel,\n cap: Nod,\n relAt: Follow,\n): ((y: number, s: number) => number) | undefined {\n const f = m.frame;\n const grid = m.hairFrontGrid;\n if (grid === undefined) return undefined;\n const { xs, ys } = grid;\n const top = ys[0];\n // Both layers must carry runs, as `outerRide` checks them.\n if (\n f.hairRuns(\"hair_front\", top) === undefined ||\n f.hairRuns(\"hair_back\", top) === undefined\n ) {\n return undefined;\n }\n const n = ys.length;\n const count = Math.round(top - ys[n - 1]);\n const hh = f.hh;\n const face = faceField(m);\n const { wr, blendAt } = renderedCrownBlend(m, ys);\n // The back hair's and the face's runs on pixel row j, indexed as the\n // front's from its top. Without the face's runs, its crop stands in.\n const backRows = new Map<number, number[]>();\n const backAt = (j: number) => {\n let runs = backRows.get(j);\n if (runs === undefined) {\n runs = f.hairRuns(\"hair_back\", top - j - 0.5)!;\n backRows.set(j, runs);\n }\n return runs;\n };\n const faceAt = (j: number) => {\n const y = top - j - 0.5;\n return (\n f.faceRuns(y) ??\n (y > f.face.y0 && y < f.face.y1 ? [f.face.x0, f.face.x1] : [])\n );\n };\n // The pixel rows row i overlaps at rest and moved by each of `dys` (model\n // dy, y up), as [first, end).\n const passed = (i: number, dys: number[]) => [\n Math.floor(i - Math.max(0, ...dys)),\n Math.ceil(i + 1 - Math.min(0, ...dys)),\n ];\n // relAt at each vertex, per side.\n const rel = new Float64Array(n * xs.length * 2).fill(NaN);\n const relOf = (r: number, c: number, k: number) => {\n const at = (r * xs.length + c) * 2 + k;\n if (Number.isNaN(rel[at])) rel[at] = relAt(xs[c], ys[r], k === 0 ? -1 : 1);\n return rel[at];\n };\n const cellR = (x: number, y: number, k: number) => {\n const { c } = gridCol(xs, x);\n const { r } = gridRow(ys, y);\n return Math.max(\n relOf(r, c, k),\n relOf(r, c + 1, k),\n relOf(r + 1, c, k),\n relOf(r + 1, c + 1, k),\n );\n };\n /** Whether c0 + a·c1 > 0 for every pair at some angle a in (0, 1]. */\n const someAngle = (pairs: [number, number][]) => {\n let lo = 0;\n let hi = 1;\n for (const [c0, c1] of pairs) {\n if (c1 === 0) {\n if (c0 <= 0) return false;\n } else if (c1 > 0) lo = Math.max(lo, -c0 / c1);\n else hi = Math.min(hi, -c0 / c1);\n }\n return lo < hi;\n };\n // Per pixel row and side (−x, +x): the least allowance ÷ R over its\n // bounded boundaries, less today's rendered blend there.\n const slack = [-1, 1].map(() => new Float64Array(count).fill(NaN));\n const slackAt = (i: number, k: number) => {\n if (!Number.isNaN(slack[k][i])) return slack[k][i];\n const y = top - i - 0.5;\n const w = blendAt(y);\n const nod: Nod = {\n up: w * NOD.hairFront.up + (1 - w) * cap.up,\n down: w * NOD.hairFront.down + (1 - w) * cap.down,\n };\n const ays = [-30, 30];\n const [b0, b1] = passed(\n i,\n ays.map((ay) => nodDy(nod, ay, hh) - nodDy(NOD.hairBack, ay, hh)),\n );\n const band: number[][] = [];\n for (let j = b0; j < b1; j++) band.push(backAt(j));\n // The face's rows and runs the row passes over relative to the face on\n // the nod — from just above the plate's top too, looking down: the bangs\n // drop further than the face there.\n const faces: { y: number; runs: number[] }[] = [];\n const [f0, f1] = passed(\n i,\n ays.map((ay) => nodDy(nod, ay, hh) - face(f.axisX, y, 0, ay)[1]),\n );\n for (let j = f0; j < f1; j++)\n faces.push({ y: top - j - 0.5, runs: faceAt(j) });\n const front = f.hairRuns(\"hair_front\", y)!;\n ([-1, 1] as const).forEach((s, side) => {\n let least = Infinity;\n const far = outerEdge(front, f.axisX, s);\n if (far !== undefined) {\n const R = cellR(far, y, side);\n const c = Math.min(...band.map((b) => runReach(b, far, s).outward));\n if (R > 0) least = Math.min(least, (m.shellScale * c) / R);\n }\n for (let t = s > 0 ? 0 : 1; t < front.length; t += 2) {\n const x = front[t];\n const R = cellR(x, y, side);\n if (R <= 0) continue;\n // A trailing boundary is its run's edge on the −s side; read as an\n // outer edge there, `inward` is how far the back's run reaches into\n // the strip it leaves.\n let c = Math.min(\n ...band.map((b) => runReach(b, x, s > 0 ? -1 : 1).inward),\n );\n // At angle a the strip lies between x moved by a × the front hair's\n // displacement at the least crown weight (the back hair's drift) and\n // at the most (the cell's largest follow), each with the shell term;\n // a face run between its ends moved by a × `faceField`'s at a full\n // turn. Every end moves linearly in a, so the angles at which the two\n // overlap are one interval.\n const sh = (m.shellScale - 1) * (x - f.axisX);\n const d0 = sh + s * m.hairBack;\n const d1 = d0 + s * R;\n const lo = Math.min(d0, d1);\n const hi = Math.max(d0, d1);\n const bares = faces.some(({ y: fy, runs }) => {\n for (let r = 0; r < runs.length; r += 2) {\n const e0 = runs[r];\n const e1 = runs[r + 1];\n const de0 = face(e0, fy, 30 * s, 0)[0];\n const de1 = face(e1, fy, 30 * s, 0)[0];\n if (\n someAngle([\n [e1 - x, de1 - lo],\n [x - e0, hi - de0],\n ])\n ) {\n return true;\n }\n }\n return false;\n });\n if (bares) c = 0;\n least = Math.min(least, (m.shellScale * c) / R);\n }\n slack[side][i] = least - w;\n });\n return slack[k][i];\n };\n // Per side, each crown vertex row's extra weight, then the monotone pass\n // up from the plate's top.\n const extra = [0, 1].map((k) => {\n const out = wr.slice();\n for (let r = 0; r < n; r++) {\n if (wr[r] >= 1) continue;\n const [i0, i1] = rowWindow(ys, r, count);\n let least = Infinity;\n for (let i = i0; i < i1; i++) least = Math.min(least, slackAt(i, k));\n out[r] = wr[r] + clamp(least, 0, 1 - wr[r]);\n }\n for (let r = n - 2; r >= 0; r--) {\n if (wr[r] < 1) out[r] = Math.max(wr[r], Math.min(out[r], out[r + 1]));\n }\n return out.map((v, r) => v - wr[r]);\n });\n return (y, s) => {\n if (s === 0) return 0;\n const e = extra[s < 0 ? 0 : 1];\n // Between vertex rows, as the render interpolates; a vertex reads its own\n // row's alone.\n const { r, t } = gridRow(ys, y, true);\n return e[r] * (1 - t) + e[r + 1] * t;\n };\n}\n\n/** The field a family moves by (AngleZ 0: the roll is the head deformer's). */\nexport function familyField(m: TurnModel, family: Family): Field {\n switch (family) {\n case \"face\":\n return faceField(m);\n case \"eye_L\":\n case \"eye_R\":\n return eyeField(m, m.boxes[family]!);\n case \"brow_L\":\n case \"brow_R\":\n return browField(m, m.boxes[family]!);\n case \"nose\":\n return noseField(m);\n case \"mouth\":\n return mouthField(m);\n case \"hair_front\":\n return hairFrontField(m);\n case \"hair_back\":\n return hairField(m, m.hairBack, NOD.hairBack);\n case \"body\":\n // The torso does not take part in the head's turn.\n return () => [0, 0];\n }\n}\n","/**\n * The face plate's mesh: the head, and — when the face layer paints them — the\n * neck and the ears as further islands of the same drawing, drawn first so the\n * head slides over them. The head island ends just under the jaw's outline and\n * along the head's own outline under each ear; the neck island runs from the\n * collar up under the jaw, its hidden top stretching the neck's first rows\n * under the jaw upward, so a chin sliding off it uncovers neck rather than the\n * chin painted there; each ear island reaches in under the head a little —\n * on the near side that tuck rides the head, on the far side it slides deeper\n * under it as the ear lags — so an ear never opens a gap beside it.\n */\n\nimport type { IkiMesh } from \"@ikijs/format\";\nimport { fadeToOutline, type HeadFrame } from \"./head\";\nimport {\n bh,\n bw,\n cellsFor,\n clamp,\n cx,\n cy,\n roundTo,\n type Box,\n type Cells,\n} from \"./layout\";\nimport { AMPLITUDE } from \"./profile\";\n\nexport type Region = \"head\" | \"neck\" | \"ear\";\n\nexport interface FaceMesh {\n mesh: IkiMesh;\n /** Per vertex: the island it belongs to. */\n region: Region[];\n /** The head island's triangles start at this index into `mesh.indices`. */\n headStart: number;\n}\n\n/** How far below the cut the neck's hidden top samples the drawing, hh: in\n * the neck's shade, clear of the jaw's own line and its darkest band, so the\n * neck a chin uncovers is one even tone. */\nconst SAMPLE_BELOW = 0.04;\n/** How far an ear island reaches in under the head's outline, hh: enough to\n * stay under the head island's edge, which follows that line only through\n * the island's columns and strays a little either side of it between them.\n * On the near side the tuck rides the head; on the far side it slides\n * deeper under it as the ear lags. */\nconst EAR_TUCK = 0.08;\n\nexport function buildFaceMesh(\n frame: HeadFrame,\n b: Box,\n head: Cells,\n neckCells: Cells,\n): FaceMesh {\n const vertices: number[] = [];\n const uvs: number[] = [];\n const region: Region[] = [];\n const pos: [number, number][] = [];\n const add = (x: number, y: number, uy: number, r: Region): number => {\n vertices.push(\n roundTo((x - cx(b)) / bw(b), 1e-5),\n roundTo((y - cy(b)) / bh(b), 1e-5),\n );\n uvs.push(\n roundTo((x - b.x0) / bw(b), 1e-5),\n roundTo((b.y1 - uy) / bh(b), 1e-5),\n );\n region.push(r);\n pos.push([x, y]);\n return region.length - 1;\n };\n // A cell's two triangles, less either one with no area (a column that\n // lies wholly outside the head collapses to its top).\n const quad = (\n out: number[],\n tl: number,\n tr: number,\n bl: number,\n br: number,\n ) => {\n for (const [p, q, t] of [\n [bl, br, tl],\n [tl, br, tr],\n ]) {\n // Two corners on one spot (a collapsed column's rows) make a sliver\n // that only rounding gives an area.\n const apart = (i: number, j: number) =>\n Math.hypot(pos[i][0] - pos[j][0], pos[i][1] - pos[j][1]) > 0.5;\n const area =\n (pos[q][0] - pos[p][0]) * (pos[t][1] - pos[p][1]) -\n (pos[t][0] - pos[p][0]) * (pos[q][1] - pos[p][1]);\n if (apart(p, q) && apart(q, t) && apart(p, t) && Math.abs(area) > 0.5)\n out.push(p, q, t);\n }\n };\n const pad = 3 + 0.1 * frame.wMax;\n // Whether the plate's paint reaches into [x0, x1] on any row between yTop\n // and yBot (its row spans are half-widths about the axis, so an off-centre\n // row gets the pad).\n const painted = (\n x0: number,\n x1: number,\n yTop: number,\n yBot: number,\n ): boolean => {\n for (let i = 0; i <= 8; i++) {\n const y = yTop + ((yBot - yTop) * i) / 8;\n const w = frame.paintedHalfAt(y) + pad;\n if (x1 >= frame.axisX - w && x0 <= frame.axisX + w) return true;\n }\n return false;\n };\n\n // A lattice whose rows run between a per-column top and bottom, cells kept\n // by `keep`; returns its triangles.\n const island = (\n xs: number[],\n rowsOf: (x: number) => { y: number; uy: number }[],\n r0: Region,\n keep: (c: number, r: number, col: { y: number }[][]) => boolean,\n ): number[] => {\n const cols = xs.map((x) => rowsOf(x));\n const ids = cols.map((col, c) => col.map((p) => add(xs[c], p.y, p.uy, r0)));\n const out: number[] = [];\n const rows = cols[0].length - 1;\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c + 1 < xs.length; c++) {\n if (!keep(c, r, cols)) continue;\n quad(out, ids[c][r], ids[c + 1][r], ids[c][r + 1], ids[c + 1][r + 1]);\n }\n }\n return out;\n };\n\n // Columns at even steps, plus the chin's and the jaw corners' own, so the\n // cut's V runs through vertices rather than chording off its tip, and the\n // chin's shade band's ends, so no cell chords the band on past them.\n const columns = (x0: number, x1: number, n: number): number[] => {\n const xs = Array.from(\n { length: n + 1 },\n (_, c) => x0 + ((x1 - x0) * c) / n,\n );\n const neck = frame.neck;\n const step = (x1 - x0) / n;\n // The head's own widest reach (its ears left out): past it a column is\n // wholly outside the head, and the head island must still reach it.\n const at = [\n frame.axisX - frame.headMax + 0.5,\n frame.axisX + frame.headMax - 0.5,\n ];\n if (neck !== undefined) {\n at.push(\n frame.axisX,\n frame.axisX - neck.half,\n frame.axisX + neck.half,\n frame.axisX - neck.waist,\n frame.axisX + neck.waist,\n );\n if (neck.bandEnd !== undefined)\n at.push(frame.axisX - neck.bandEnd, frame.axisX + neck.bandEnd);\n }\n // Each takes the even column near it (not an end), or one of its own —\n // never a column another has taken, so none of them is lost; one near an\n // end is left to it, and one within half a pixel of a taken column is that\n // column.\n const placed = new Set<number>();\n for (const k of at) {\n if (k <= x0 || k >= x1) continue;\n if ([...placed].some((i) => Math.abs(xs[i] - k) < 0.5)) continue;\n const near = xs.findIndex(\n (x, i) => !placed.has(i) && Math.abs(x - k) < 0.3 * step,\n );\n if (near > 0 && near < n) {\n xs[near] = k;\n placed.add(near);\n } else if (near < 0) placed.add(xs.push(k) - 1);\n }\n return xs.sort((a, b) => a - b);\n };\n\n const indices: number[] = [];\n const neck = frame.neck;\n if (neck !== undefined) {\n const span = neck.span + pad;\n const nc = cellsFor(2 * span, neckCells.px, neckCells.min, neckCells.max);\n // Inside the crop: a collar flaring nearly as wide as the plate must not\n // put a vertex's texture off it.\n const xs = columns(\n Math.max(b.x0, frame.axisX - span),\n Math.min(b.x1, frame.axisX + span),\n nc,\n );\n // The hidden rows show the drawing SAMPLE_BELOW under the cut, thinning\n // to the row just under it at the neck's outline (which must run on\n // unbroken above the cut). Under the chin that is the neck below the\n // shade band the head carries; past the band's end, where the cut runs\n // just under the stroke, it is whatever shade the neck keeps there.\n const sampleBelow = (x: number) =>\n Math.max(\n 1,\n SAMPLE_BELOW *\n frame.hh *\n fadeToOutline(Math.abs(x - frame.axisX), neck),\n );\n // The jaw's corners: the highest the cut runs across the neck. Beside\n // the neck a column's cut is the head's own side outline instead, up the\n // cheek (or, past the head's widest reach, the plate's top): there the\n // island only carries what the plate paints under the jaw's corners — a\n // collar's flare — or it would hold a still copy of the cheek beside the\n // turning head.\n let highest = -Infinity;\n for (const x of xs) {\n if (Math.abs(x - frame.axisX) <= neck.half)\n highest = Math.max(highest, frame.cutAt(x));\n }\n const cutOf = (x: number) => Math.min(frame.cutAt(x), highest);\n // One level top, above the jaw's corners: a top following the jaw's V\n // would show its own diagonal edge once the chin slides and lifts off it.\n const top = Math.min(b.y1, highest + AMPLITUDE.hiddenNeck * frame.hh);\n const realRows = cellsFor(\n highest - b.y0,\n neckCells.px,\n neckCells.min,\n neckCells.max,\n );\n // Two rows reaching up under the jaw, a third a pixel above the cut, all\n // showing the neck's shade; then the neck as drawn, from the cut down.\n const hiddenRows = 3;\n indices.push(\n ...island(\n xs,\n (x) => {\n const cut = cutOf(x);\n const sample = Math.max(b.y0, cut - sampleBelow(x));\n const pts: { y: number; uy: number }[] = [\n { y: top, uy: sample },\n { y: (top + cut) / 2, uy: sample },\n { y: cut + 1, uy: sample },\n { y: cut, uy: cut },\n ];\n // Level rows, shared by every column (a column's own rows above\n // its cut collapse onto it): the neck's cells stay square rather\n // than slanting with the jaw's V.\n for (let r = 1; r <= realRows; r++) {\n const y = Math.min(\n cut,\n highest - ((highest - b.y0) * r) / realRows,\n );\n pts.push({ y, uy: y });\n }\n return pts;\n },\n \"neck\",\n (c, r, cols) => {\n const top = Math.max(cols[c][r].y, cols[c + 1][r].y);\n const bot = Math.min(cols[c][r + 1].y, cols[c + 1][r + 1].y);\n if (r < hiddenRows) {\n // The hidden rows show the drawing just under the jaw.\n const mid = (xs[c] + xs[c + 1]) / 2;\n const y = Math.max(b.y0, cutOf(mid) - sampleBelow(mid));\n return painted(xs[c], xs[c + 1], y, y);\n }\n return painted(xs[c], xs[c + 1], top, bot);\n },\n ),\n );\n }\n const ears = frame.ears;\n if (ears !== undefined) {\n // Rows over the band, each running from under the head's outline (by\n // EAR_TUCK) out past the ear.\n const tuck = EAR_TUCK * frame.hh;\n const yTop = Math.min(b.y1, ears.top + 2);\n const yBot = Math.max(b.y0, ears.bottom - 2);\n const nr = cellsFor(yTop - yBot, 16, 3, 10);\n const outer = ears.outer + pad;\n let inner = Infinity;\n for (let r = 0; r <= nr; r++)\n inner = Math.min(inner, ears.attachAt(yTop - ((yTop - yBot) * r) / nr));\n const nc = cellsFor(outer - (inner - tuck), 12, 2, 6);\n for (const side of [-1, 1] as const) {\n const ids: number[][] = [];\n const xsOf: number[][] = [];\n for (let r = 0; r <= nr; r++) {\n const y = yTop - ((yTop - yBot) * r) / nr;\n const d0 = Math.max(0, ears.attachAt(y) - tuck);\n const row: number[] = [];\n const xs: number[] = [];\n for (let c = 0; c <= nc; c++) {\n // Left to right whichever side, so the cells wind as the head's.\n const k = side < 0 ? nc - c : c;\n const x = clamp(\n frame.axisX + side * (d0 + ((outer - d0) * k) / nc),\n b.x0,\n b.x1,\n );\n xs.push(x);\n row.push(add(x, y, y, \"ear\"));\n }\n ids.push(row);\n xsOf.push(xs);\n }\n for (let r = 0; r < nr; r++) {\n for (let c = 0; c < nc; c++) {\n const x0 = Math.min(xsOf[r][c], xsOf[r + 1][c]);\n const x1 = Math.max(xsOf[r][c + 1], xsOf[r + 1][c + 1]);\n const yt = yTop - ((yTop - yBot) * r) / nr;\n const yb = yTop - ((yTop - yBot) * (r + 1)) / nr;\n if (!painted(x0, x1, yt, yb)) continue;\n quad(\n indices,\n ids[r][c],\n ids[r][c + 1],\n ids[r + 1][c],\n ids[r + 1][c + 1],\n );\n }\n }\n }\n }\n\n const headStart = indices.length;\n const cols = cellsFor(bw(b), head.px, head.min, head.max);\n const rows = cellsFor(bh(b), head.px, head.min, head.max);\n const xs = columns(b.x0, b.x1, cols);\n indices.push(\n ...island(\n xs,\n (x) => {\n const bottom = Math.max(b.y0, frame.cutAt(x));\n return Array.from({ length: rows + 1 }, (_, r) => {\n const y = b.y1 - ((b.y1 - bottom) * r) / rows;\n return { y, uy: y };\n });\n },\n \"head\",\n (c, r, cols) => {\n // A column wholly outside the head (past the ears' reach, beside the\n // neck) has collapsed to its top: fanning cells out of it would\n // sweep over the ear.\n const height = (k: number) =>\n cols[k][0].y - cols[k][cols[k].length - 1].y;\n if (height(c) < 1 || height(c + 1) < 1) return false;\n return painted(\n xs[c],\n xs[c + 1],\n Math.max(cols[c][r].y, cols[c + 1][r].y),\n Math.min(cols[c][r + 1].y, cols[c + 1][r + 1].y),\n );\n },\n ),\n );\n return { mesh: { vertices, uvs, indices }, region, headStart };\n}\n","/**\n * Turning the profile into this character's turn, fitting any cue a caller\n * measured, keeping the features inside the art's room, and reporting what\n * the rig then renders.\n *\n * With no target the turn is the profile's (times the style's knobs). A given\n * cue is fitted by the one knob it reads: eyeShift by the turn's amount,\n * farEyeRatio by the eyes' foreshortening, silhouetteRatio by the hair's\n * width, noseShift and mouthShift by those features' own shift. The room the\n * art leaves — the far eye inside the plate's outline, the far iris clear of\n * the bangs' side strand, the nose and mouth inside the plate, the far ear's\n * slide under the head — caps the turn (or that feature, or the plate's\n * narrowing) and says so in `clamped`.\n */\n\nimport type { HeadFrame } from \"./head\";\nimport { cy, type Box } from \"./layout\";\nimport { roleSpec, type Family } from \"./roles\";\nimport {\n chinSlide,\n familyField,\n farEarCovered,\n type TurnModel,\n} from \"./fields\";\nimport { TURN, type ResolvedStyle } from \"./profile\";\nimport {\n TurnTargetError,\n type IrisStrand,\n type StrandOverlap,\n type TurnSolveReport,\n type TurnTargets,\n} from \"./types\";\n\n// --- targets ----------------------------------------------------------------\n\nexport type ResolvedTargets = Partial<Record<keyof TurnTargets, number>> & {\n /** The fields the caller passed. */\n given: Set<keyof TurnTargets>;\n};\n\nconst RANGES: Record<keyof TurnTargets, [number, number, boolean]> = {\n // [lo, hi, lo exclusive]\n eyeShift: [-1, 1, false],\n farEyeRatio: [0, 1.5, true],\n silhouetteRatio: [0.5, 1.5, false],\n noseShift: [-1, 1, false],\n mouthShift: [-1, 1, false],\n headHalfWidth: [0, Infinity, true],\n};\n\n/** Every field `TurnTargets` has: a caller's names only these. */\nexport const TURN_TARGET_KEYS = Object.keys(RANGES) as (keyof TurnTargets)[];\n\n/** The shifts are magnitudes: `measure_turn_reference` signs them by the\n * reference's turn direction, and the rig turns both ways. */\nconst SHIFTS: ReadonlySet<keyof TurnTargets> = new Set([\n \"eyeShift\",\n \"noseShift\",\n \"mouthShift\",\n]);\n\nexport function checkedNumber(\n name: string,\n v: unknown,\n lo: number,\n hi: number,\n open = false,\n): number {\n if (typeof v !== \"number\" || !Number.isFinite(v)) {\n throw new TurnTargetError(\n `${name} must be a finite number, got ${String(v)}`,\n );\n }\n if ((open ? v <= lo : v < lo) || v > hi) {\n throw new TurnTargetError(\n `${name} ${v} is outside ${open ? \"(\" : \"[\"}${lo}, ${hi}]`,\n );\n }\n return v;\n}\n\n/** An options object a caller passed: absent, or a plain object naming only\n * the fields it has — a misspelt one would otherwise do nothing. */\nexport function checkedKeys(\n name: string,\n v: unknown,\n known: readonly string[],\n): void {\n if (v === undefined) return;\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n throw new TurnTargetError(`${name} must be a plain object`);\n }\n for (const key of Object.keys(v)) {\n if (!known.includes(key)) {\n throw new TurnTargetError(\n `${name}.${key} is not one of ${known.join(\", \")}`,\n );\n }\n }\n}\n\nexport function resolveTurnTargets(\n tt: TurnTargets | undefined,\n plateHalf: number,\n): ResolvedTargets {\n const out: ResolvedTargets = { given: new Set() };\n for (const key of TURN_TARGET_KEYS) {\n const v: unknown = tt?.[key];\n if (v === undefined) continue;\n const [lo, hi, open] = RANGES[key];\n const checked = checkedNumber(`turnTargets.${key}`, v, lo, hi, open);\n out[key] = SHIFTS.has(key) ? Math.abs(checked) : checked;\n if (key !== \"headHalfWidth\") out.given.add(key);\n }\n if (out.headHalfWidth !== undefined && out.headHalfWidth <= plateHalf) {\n throw new TurnTargetError(\n `turnTargets.headHalfWidth ${out.headHalfWidth} is not wider than the face plate (half-width ${plateHalf}): the silhouette would sit inside the face`,\n );\n }\n return out;\n}\n\n// --- cue geometry -----------------------------------------------------------\n\nexport interface IrisRow {\n role: string;\n /** Painted x-span on the iris's centre row, model. */\n lo: number;\n hi: number;\n y: number;\n}\n\nexport interface SolveContext {\n frame: HeadFrame;\n /** The iris (or, without irises, the eye) on the −x and the +x side. */\n left: IrisRow;\n right: IrisRow;\n /** Every role drawing the silhouette at the eye row, per side (boundary x). */\n candidates: {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n };\n /** Half that silhouette's rest span: what a render of the rig measures the\n * head as, and so what every shift cue is a fraction of. */\n restHalf: number;\n strand?: { left?: IrisStrand; right?: IrisStrand };\n hasHairFront: boolean;\n /** The eye whites on the −x and the +x side. */\n eyeBoxes: { left: Box; right: Box };\n noseAt?: { x: number; y: number };\n noseBox?: Box;\n mouthAt: { x: number; y: number };\n mouthBox: Box;\n}\n\n/** Landed x of a rest point on a role's part, at (AngleX `ax`, AngleY 0). */\nexport type Lander = (role: string, x: number, y: number, ax: number) => number;\n\n/** Lands through the family fields themselves: what the fit iterates on. */\nexport function analyticLander(m: TurnModel): Lander {\n const cache = new Map<Family, ReturnType<typeof familyField>>();\n return (role, x, y, ax) => {\n const family = roleSpec(role).family;\n let f = cache.get(family);\n if (f === undefined) {\n f = familyField(m, family);\n cache.set(family, f);\n }\n return x + f(x, y, ax, 0)[0];\n };\n}\n\ninterface Cues {\n eyeShift: number;\n farEyeRatio: number;\n silhouetteRatio: number;\n}\n\n/** The three cues `measure_turn_reference` reads, for a turn of `ax`. */\nfunction cuesAt(ctx: SolveContext, land: Lander, ax: number): Cues {\n const { left: L, right: R } = ctx;\n const l0 = land(L.role, L.lo, L.y, ax);\n const l1 = land(L.role, L.hi, L.y, ax);\n const r0 = land(R.role, R.lo, R.y, ax);\n const r1 = land(R.role, R.hi, R.y, ax);\n const wl = l1 - l0;\n const wr = r1 - r0;\n const wl0 = L.hi - L.lo;\n const wr0 = R.hi - R.lo;\n const ratio = ax < 0 ? wl / wr / (wl0 / wr0) : wr / wl / (wr0 / wl0);\n const pc0 = (L.lo + L.hi + R.lo + R.hi) / 4;\n const pc = (l0 + l1 + r0 + r1) / 4;\n const y = ctx.frame.eyeY;\n const hl0 = Math.min(...ctx.candidates.left.map((c) => c.x));\n const hr0 = Math.max(...ctx.candidates.right.map((c) => c.x));\n const hl = Math.min(\n ...ctx.candidates.left.map((c) => land(c.role, c.x, y, ax)),\n );\n const hr = Math.max(\n ...ctx.candidates.right.map((c) => land(c.role, c.x, y, ax)),\n );\n const half0 = ctx.restHalf;\n return {\n eyeShift: (pc - (hl + hr) / 2 - (pc0 - (hl0 + hr0) / 2)) / half0,\n farEyeRatio: ratio,\n silhouetteRatio: (hr - hl) / 2 / half0,\n };\n}\n\n/** Both turn directions, as magnitudes. */\nexport function meanCues(ctx: SolveContext, land: Lander): Cues {\n const a = cuesAt(ctx, land, -30);\n const b = cuesAt(ctx, land, 30);\n return {\n eyeShift: (Math.abs(a.eyeShift) + Math.abs(b.eyeShift)) / 2,\n farEyeRatio: (a.farEyeRatio + b.farEyeRatio) / 2,\n silhouetteRatio: (a.silhouetteRatio + b.silhouetteRatio) / 2,\n };\n}\n\n// --- strand coverage ----------------------------------------------------------\n\n/** How much of a far iris's painted row the bangs' run covers, px. */\nfunction coverage(\n strand: IrisStrand,\n side: -1 | 1,\n ctx: SolveContext,\n land: Lander,\n ax: number,\n): number {\n const iris = side < 0 ? ctx.left : ctx.right;\n const a = land(iris.role, strand.irisOuter, strand.y, ax);\n const b = land(iris.role, strand.irisInner, strand.y, ax);\n const ro = land(\"hair_front\", strand.runOuter, strand.y, ax);\n let lo: number;\n let hi: number;\n if (strand.runFace === null) {\n // A fringe spanning the face runs on inward without end.\n lo = side < 0 ? ro : -Infinity;\n hi = side < 0 ? Infinity : ro;\n } else {\n const rf = land(\"hair_front\", strand.runFace, strand.y, ax);\n lo = Math.min(ro, rf);\n hi = Math.max(ro, rf);\n }\n return Math.max(\n 0,\n Math.min(hi, Math.max(a, b)) - Math.max(lo, Math.min(a, b)),\n );\n}\n\n/** The side's far stops: the −x iris is the far one when turning toward −x. */\nconst farStops = (side: -1 | 1) => (side < 0 ? [-15, -30] : [15, 30]);\n\nexport function strandOverlaps(\n ctx: SolveContext,\n land: Lander,\n holdBase: number,\n): { left?: StrandOverlap; right?: StrandOverlap } | undefined {\n const out: { left?: StrandOverlap; right?: StrandOverlap } = {};\n for (const [key, side] of [\n [\"left\", -1],\n [\"right\", 1],\n ] as const) {\n const strand = ctx.strand?.[key];\n if (strand === undefined) continue;\n const restPx = coverage(strand, side, ctx, land, 0);\n let px = 0;\n let deg = farStops(side)[1];\n for (const ax of farStops(side)) {\n const c = coverage(strand, side, ctx, land, ax);\n if (c > px) {\n px = c;\n deg = ax;\n }\n }\n if (px <= 0) continue;\n out[key] = {\n deg,\n px: round3(px),\n hh: round3(px) / holdBase,\n restPx: round3(restPx),\n // A fringe spanning the face has no side to hold the iris clear of.\n held: strand.runFace !== null && px <= restPx + STRAND_SLACK,\n };\n }\n return out.left || out.right ? out : undefined;\n}\n\nconst round3 = (v: number) => Math.round(v * 1000) / 1000;\n\n/** Sub-pixel slack in \"no deeper under the strand than painted\". */\nconst STRAND_SLACK = 0.5;\n\n// --- the fit ----------------------------------------------------------------\n\n/** The knobs the fit turns (see `buildTurn`). */\nexport interface TurnParams {\n /** The whole turn's amount (1 = the profile). */\n turn: number;\n /** The features' lead over the plate (1 = the profile). */\n lead: number;\n /** The front hair's share of the plate's turn. */\n follow: number;\n /** Its outer edge's share (the head's outline where it draws it). */\n outline: number;\n /** The eyes' foreshortening per unit of turn (1 = the profile's, at the\n * profile's turn). */\n fore: number;\n /** The hair's width at full turn (the silhouette). */\n shell: number;\n /** A nose or mouth shift fitted or capped on its own, px. */\n nose?: number;\n mouth?: number;\n}\n\nexport type Build = (p: TurnParams) => TurnModel;\n\nexport interface TurnFit {\n model: TurnModel;\n clamped: (keyof TurnTargets)[];\n}\n\nfunction bisect(\n f: (v: number) => number,\n lo: number,\n hi: number,\n it = 50,\n): number {\n // f(lo) and f(hi) bracket 0 with f increasing.\n for (let i = 0; i < it; i++) {\n const mid = (lo + hi) / 2;\n if (f(mid) < 0) lo = mid;\n else hi = mid;\n }\n return (lo + hi) / 2;\n}\n\n/** The largest v in [0, hi] with ok(v), ok being true at 0 and monotone. */\nfunction largestOk(ok: (v: number) => boolean, hi: number): number {\n if (ok(hi)) return hi;\n let lo = 0;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (ok(mid)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n\nconst fmt = (v: number) => v.toFixed(5);\n\n/** The most the turn and the foreshortening may be scaled while fitting. */\nconst TURN_MAX = 3;\nconst FORE_RANGE: [number, number] = [-1, 4];\nconst SHELL_RANGE: [number, number] = [0.8, 1.2];\n\nexport function fitTurn(\n ctx: SolveContext,\n targets: ResolvedTargets,\n style: ResolvedStyle,\n build: Build,\n): TurnFit {\n const clamped: (keyof TurnTargets)[] = [];\n // A given eyeShift fits the turn's amount, so the style's own amount has\n // no say: the fit starts from the profile, the eyes' foreshortening with it.\n const styleTurn = targets.eyeShift === undefined ? style.turn : 1;\n const p: TurnParams = {\n turn: styleTurn,\n lead: style.featureLead,\n follow: style.hairFollow,\n outline: style.outlineFollow,\n fore: 1,\n shell: 1,\n };\n const cues = (q: TurnParams) => meanCues(ctx, analyticLander(build(q)));\n\n // The turn's amount (eyeShift) and the eyes' foreshortening\n // (farEyeRatio): each cue leans a little on the other knob, so a few\n // rounds. The foreshortening is fitted as its product with the turn — the\n // eyes' own width change — so a small turn can still ask for it.\n let short = false;\n const fitTurnAmount = () => {\n if (targets.eyeShift === undefined) return;\n const e = targets.eyeShift;\n const g = p.fore * p.turn;\n const at = (turn: number) =>\n cues({ ...p, turn, fore: g / Math.max(turn, 1e-9) }).eyeShift;\n short = at(TURN_MAX) < e;\n const turn = short ? TURN_MAX : bisect((t) => at(t) - e, 1e-6, TURN_MAX);\n p.fore = g / turn;\n p.turn = turn;\n };\n const fitFore = () => {\n if (targets.farEyeRatio === undefined) return;\n const r = targets.farEyeRatio;\n const at = (g: number) =>\n cues({ ...p, fore: g / Math.max(p.turn, 1e-9) }).farEyeRatio;\n const hi = at(FORE_RANGE[0]);\n const lo = at(FORE_RANGE[1]);\n if (r > hi + 1e-9 || r < lo - 1e-9) {\n throw new TurnTargetError(\n `turnTargets.farEyeRatio ${r} is unreachable on this layer set: attainable ${fmt(lo)}…${fmt(hi)}`,\n );\n }\n p.fore =\n bisect((g) => r - at(g), FORE_RANGE[0], FORE_RANGE[1]) /\n Math.max(p.turn, 1e-9);\n };\n for (let i = 0; i < 3; i++) {\n fitTurnAmount();\n fitFore();\n }\n // The room: the far eye stays inside the plate, the chin over the neck it\n // slides across, and — best effort — the far iris clear of its strand. A\n // strand that leaves less than half the profile's own turn is left to\n // overlap (reported), not obeyed.\n const g = p.fore * p.turn;\n const withTurn = (turn: number) =>\n build({ ...p, turn, fore: g / Math.max(turn, 1e-9) });\n const plateTurn = largestOk(\n (turn) =>\n eyesInPlate(ctx, withTurn(turn)) && chinOverNeck(ctx, withTurn(turn)),\n p.turn,\n );\n const strandTurn = largestOk(\n (turn) => strandHeld(ctx, withTurn(turn)),\n p.turn,\n );\n let turn = Math.min(p.turn, plateTurn);\n if (strandTurn >= 0.5 * Math.min(p.turn, styleTurn))\n turn = Math.min(turn, strandTurn);\n if (turn < p.turn - 1e-6 || short) {\n p.fore = g / Math.max(turn, 1e-9);\n p.turn = turn;\n clamped.push(\"eyeShift\");\n }\n fitFore();\n\n // The hair's width at full turn.\n if (targets.silhouetteRatio !== undefined) {\n const s = targets.silhouetteRatio;\n const at = (shell: number) => cues({ ...p, shell }).silhouetteRatio;\n const lo = at(SHELL_RANGE[0]);\n const hi = at(SHELL_RANGE[1]);\n if (s < lo - 1e-9 || s > hi + 1e-9) {\n throw new TurnTargetError(\n `turnTargets.silhouetteRatio ${s} is unreachable on this layer set: attainable ${fmt(lo)}…${fmt(hi)}`,\n );\n }\n p.shell = bisect((k) => at(k) - s, SHELL_RANGE[0], SHELL_RANGE[1]);\n }\n // ... narrowing the plate (without hair) only as far as the head still\n // covers the far ear's slide on the line under it: its outer edge keeps\n // its lag, and its tucked strip stays under the head. A wider shell moves\n // that line further, so the least that covers it is found by halving.\n const covered = (shell: number) => farEarCovered(build({ ...p, shell }));\n if (!covered(p.shell) && covered(Math.max(1, p.shell))) {\n let lo = p.shell;\n let hi = Math.max(1, p.shell);\n for (let i = 0; i < 50; i++) {\n const mid = (lo + hi) / 2;\n if (covered(mid)) hi = mid;\n else lo = mid;\n }\n p.shell = hi;\n clamped.push(\"silhouetteRatio\");\n }\n\n // The nose and the mouth: each its own shift, inside the plate — as the\n // eye shift, a fraction of the head a render spans at the eye row.\n const hb = ctx.restHalf;\n const feature = (\n key: \"noseShift\" | \"mouthShift\",\n family: \"nose\" | \"mouth\",\n at: { x: number; y: number },\n box: Box,\n ) => {\n const base = build(p);\n const own = family === \"nose\" ? base.nose : base.mouth;\n const withPx = (px: number) => build({ ...p, [family]: px });\n const shiftOf = (px: number) => {\n const f = familyField(withPx(px), family);\n return (\n (Math.abs(f(at.x, at.y, -30, 0)[0]) +\n Math.abs(f(at.x, at.y, 30, 0)[0])) /\n 2 /\n hb\n );\n };\n // No slower than the plate under it, no further than its room.\n const floorPx = base.face;\n const ceilPx = largestOk(\n (px) => px <= floorPx || featureInPlate(ctx, withPx(px), family, box),\n Math.max(own, floorPx) * 3,\n );\n const asked = targets[key];\n if (asked !== undefined) {\n const lo = shiftOf(floorPx);\n const hi = shiftOf(Math.max(floorPx, ceilPx));\n if (asked < lo - 1e-6 || asked > hi + 1e-6) {\n throw new TurnTargetError(\n `turnTargets.${key} ${asked} is unreachable on this layer set: attainable ${fmt(lo)}…${fmt(hi)}`,\n );\n }\n p[family] = bisect(\n (px) => shiftOf(px) - asked,\n floorPx,\n Math.max(floorPx, ceilPx),\n );\n } else if (own > ceilPx) {\n p[family] = Math.max(floorPx, ceilPx);\n clamped.push(key);\n }\n };\n if (ctx.noseAt && ctx.noseBox) {\n feature(\"mouthShift\", \"mouth\", ctx.mouthAt, ctx.mouthBox);\n feature(\"noseShift\", \"nose\", ctx.noseAt, ctx.noseBox);\n }\n return { model: build(p), clamped };\n}\n\n// --- room -------------------------------------------------------------------\n\n/** A feature's far edge stays this fraction of its row's half-width inside\n * the plate's own far edge (the eyes: a pixel). */\nconst FEATURE_ROOM = 0.05;\nconst EYE_ROOM = 1;\n\nfunction plateEdge(\n ctx: SolveContext,\n land: Lander,\n y: number,\n side: -1 | 1,\n ax: number,\n): number {\n const w = ctx.frame.paintedHalfAt(y);\n return land(\"face\", ctx.frame.axisX + side * w, y, ax);\n}\n\n/** The far eye's far corner stays inside the plate's outline on its row —\n * unless a side strand frames that eye: the strand covers the outline\n * there, and the iris's own bound against it is what shows. */\nfunction eyesInPlate(ctx: SolveContext, m: TurnModel): boolean {\n const land = analyticLander(m);\n for (const [side, box, role, key] of [\n [-1, ctx.eyeBoxes.left, ctx.left.role, \"left\"],\n [1, ctx.eyeBoxes.right, ctx.right.role, \"right\"],\n ] as const) {\n const strand = ctx.strand?.[key];\n if (strand !== undefined && strand.runFace !== null) continue;\n const eyeRole = role.replace(/^iris_/, \"eye_\");\n const y = cy(box);\n const ax = 30 * side;\n const corner = land(eyeRole, side < 0 ? box.x0 : box.x1, y, ax);\n const edge = plateEdge(ctx, land, y, side, ax);\n const restIn =\n side *\n (ctx.frame.axisX +\n side * ctx.frame.paintedHalfAt(y) -\n (side < 0 ? box.x0 : box.x1));\n // An eye painted past the plate's outline may not go further past it.\n if (side * (edge - corner) < Math.min(EYE_ROOM, restIn)) return false;\n }\n return true;\n}\n\n/** The chin stays over the neck it slides across: past the neck's own\n * width, the neck's hidden top would come out from under the jaw. */\nfunction chinOverNeck(ctx: SolveContext, m: TurnModel): boolean {\n const { frame } = ctx;\n if (frame.neck === undefined) return true;\n return chinSlide(m) <= frame.neck.half;\n}\n\n/** The far iris goes no deeper under its bangs' strand than it is painted. */\nfunction strandHeld(ctx: SolveContext, m: TurnModel): boolean {\n const land = analyticLander(m);\n for (const [key, side] of [\n [\"left\", -1],\n [\"right\", 1],\n ] as const) {\n const strand = ctx.strand?.[key];\n if (strand === undefined || strand.runFace === null) continue;\n const rest = coverage(strand, side, ctx, land, 0);\n for (const ax of farStops(side)) {\n if (coverage(strand, side, ctx, land, ax) > rest + STRAND_SLACK)\n return false;\n }\n }\n return true;\n}\n\n/** A nose or mouth stays on the plate: its far edge keeps FEATURE_ROOM of its\n * row's half-width inside the plate's own far edge. */\nfunction featureInPlate(\n ctx: SolveContext,\n m: TurnModel,\n family: \"nose\" | \"mouth\",\n box: Box,\n): boolean {\n const land = analyticLander(m);\n const y = cy(box);\n const w = ctx.frame.paintedHalfAt(y);\n for (const side of [-1, 1] as const) {\n const ax = 30 * side;\n const far = land(family, side < 0 ? box.x0 : box.x1, y, ax);\n const edge = plateEdge(ctx, land, y, side, ax);\n if (side * (edge - far) < FEATURE_ROOM * w) return false;\n }\n return true;\n}\n\n// --- the report ---------------------------------------------------------------\n\nexport function turnReport(\n ctx: SolveContext,\n fit: TurnFit,\n rendered: Lander,\n): TurnSolveReport {\n const { frame } = ctx;\n const m = fit.model;\n const hb = frame.holdBase;\n const achieved = meanCues(ctx, rendered);\n // A shift at ±30 as the depth a rotation would need for it.\n const depth = (px: number) => px / Math.sin(Math.PI / 6);\n const eye = depth((m.eye.far + m.eye.near) / 2);\n const plate = depth(m.face);\n const w = frame.paintedHalfAt(frame.eyeY);\n const report: TurnSolveReport = {\n radius: round3((w * w) / (2 * Math.max(1e-3, eye - plate))),\n holdBase: hb,\n depths: {\n eye: round4(eye / hb),\n nose: round4(depth(m.nose) / hb),\n mouth: round4(depth(m.mouth) / hb),\n },\n achieved: {\n eyeShift: round4(achieved.eyeShift),\n farEyeRatio: round4(achieved.farEyeRatio),\n silhouetteRatio: round4(achieved.silhouetteRatio),\n },\n clamped: fit.clamped,\n };\n const overlap = strandOverlaps(ctx, rendered, hb);\n if (overlap !== undefined) report.strandOverlap = overlap;\n return report;\n}\n\nconst round4 = (v: number) => Math.round(v * 10000) / 10000;\n\n/** The turn model the knobs give: the profile, in this head's px. */\nexport function buildTurn(\n frame: HeadFrame,\n landmarks: Pick<\n TurnModel,\n \"boxes\" | \"noseAt\" | \"noseTopY\" | \"mouthAt\" | \"hairTop\" | \"hairFrontGrid\"\n >,\n q: TurnParams,\n): TurnModel {\n const hh = frame.hh;\n const A = q.turn;\n const face = A * hh * TURN.face;\n const lead = (v: number) => face + A * q.lead * hh * (v - TURN.face);\n // How far the far eye's outer corner goes: its shift, less its own\n // narrowing about its centre.\n const eyes = [landmarks.boxes.eye_L, landmarks.boxes.eye_R].filter(\n (e): e is NonNullable<typeof e> => e !== undefined,\n );\n const eyeHalf =\n eyes.reduce((sum, e) => sum + (e.x1 - e.x0) / 2, 0) /\n Math.max(1, eyes.length);\n const farScale = 1 + q.fore * A * (TURN.eyeFarScale - 1);\n const farCorner = lead(TURN.eyeFar) - (1 - farScale) * eyeHalf;\n return {\n frame,\n face,\n chinLead: A * q.lead * hh * TURN.chinLead,\n widthUpper: 1 + A * (TURN.widthUpper - 1),\n widthJaw: 1 + A * (TURN.widthJaw - 1),\n eye: { far: lead(TURN.eyeFar), near: lead(TURN.eyeNear) },\n // The eyes foreshorten as much as the head turns.\n eyeScale: {\n far: 1 + q.fore * A * (TURN.eyeFarScale - 1),\n near: 1 + q.fore * A * (TURN.eyeNearScale - 1),\n },\n brow: { far: lead(TURN.browFar), near: lead(TURN.browNear) },\n nose: q.nose ?? lead(TURN.nose),\n mouth: q.mouth ?? lead(TURN.mouth),\n mouthWidth: 1 + A * (TURN.mouthWidth - 1),\n tilt: A,\n hairFront: q.follow * face,\n hairFar: Math.max(q.follow * face, farCorner),\n hairOuter: q.outline * face,\n hairBack: A * hh * TURN.hairBack,\n shellScale: q.shell,\n earFarScale: 1 + A * (TURN.earFarScale - 1),\n ...landmarks,\n };\n}\n","/**\n * Everything a part does besides the head turn: the blink fold, gaze, brows,\n * mouth, hair sway, and the hang of hair and the neck's stillness under a\n * roll. Each is a per-vertex warp in the part's own ±0.5 space or a binding,\n * applied before the part's turn grid, so the turn carries it. Amplitudes are\n * the profile's (`profile.ts`).\n */\n\nimport {\n StandardParameter as P,\n type IkiBinding,\n type IkiMesh,\n type IkiWarp,\n} from \"@ikijs/format\";\nimport {\n bh,\n bw,\n cx,\n DEG,\n meshPoints,\n roundTo,\n smoothstep,\n type Box,\n} from \"./layout\";\nimport { AMPLITUDE, ROLL_DEG } from \"./profile\";\n\n/** Hair sway parameters' range: a physics output, in degrees of swing. */\nexport const SWAY_RANGE = 20;\n/** The sway grows down the layer as (distance from its top)^SWAY_CURVE. */\nconst SWAY_CURVE = 1.4;\n/** The share of a roll the long hair gives back by hanging. */\nconst HAIR_HANG = 0.35;\n/** Roll stops for the hang and the neck: the profile's roll (`ROLL_DEG`),\n * which the linear blend between 0 and ±30 carries within about a pixel. */\nexport const Z_STOPS = [-30, 0, 30];\n\ntype Vec = [number, number];\n\n/** A warp whose keyform at each value is the model-space displacement `f`\n * gives each vertex (`i` its index), stored in the part's local units. */\nexport function localWarp(\n parameter: string,\n mesh: IkiMesh,\n box: Box,\n values: number[],\n f: (p: Vec, value: number, i: number) => Vec,\n): IkiWarp {\n const pts = meshPoints(mesh, box);\n const w = bw(box);\n const h = bh(box);\n return {\n parameter,\n keyforms: values.map((value) => ({\n value,\n offsets: pts.flatMap((p, i) => {\n const [dx, dy] = f(p, value, i);\n return [roundTo(dx / w, 1e-4), roundTo(dy / h, 1e-4)];\n }),\n })),\n };\n}\n\n/** The roll AngleZ `v` gives the head, radians, CCW-positive (AngleZ is\n * clockwise-positive, Live2D's). */\nexport const rollOf = (v: number): number => (-v / 30) * ROLL_DEG * DEG;\n\n/** How far past its own box, per side, a part's vertices can travel under\n * its warps (each at its extremes, summed) and its translate bindings —\n * the margin its turn grid must cover, or the engine clamps it flat. */\nexport interface Reach {\n left: number;\n right: number;\n bottom: number;\n top: number;\n}\n\nexport function motionReach(\n warps: IkiWarp[] | undefined,\n mesh: IkiMesh | undefined,\n box: Box,\n extra: Vec = [0, 0],\n): Reach {\n const out: Reach = {\n left: extra[0],\n right: extra[0],\n bottom: extra[1],\n top: extra[1],\n };\n if (mesh === undefined) return out;\n const pts = meshPoints(mesh, box);\n for (const warp of warps ?? []) {\n let l = 0;\n let r = 0;\n let b = 0;\n let t = 0;\n for (const k of warp.keyforms) {\n pts.forEach(([x, y], i) => {\n const px = x + k.offsets[2 * i] * bw(box);\n const py = y + k.offsets[2 * i + 1] * bh(box);\n l = Math.max(l, box.x0 - px);\n r = Math.max(r, px - box.x1);\n b = Math.max(b, box.y0 - py);\n t = Math.max(t, py - box.y1);\n });\n }\n out.left += l;\n out.right += r;\n out.bottom += b;\n out.top += t;\n }\n return out;\n}\n\n// --- eyes ---------------------------------------------------------------------\n\n/** The eye white folds shut onto a crease, the upper lid coming `travel` of\n * the eye's height down; as its clip region closes, the iris is cut away\n * rather than squashed. Shut, it has no height at all: any band left open\n * shows a strip of iris under the lash. A lower lash (`box`, drawn over the\n * iris) folds onto the same crease of its `eye`, so it moves with the\n * white's rows and closes into the seam under the upper lash. */\nexport function blinkFold(\n param: string,\n mesh: IkiMesh,\n box: Box,\n travel: number,\n eye: Box = box,\n): IkiWarp {\n const yc = eye.y1 - travel * bh(eye);\n return localWarp(param, mesh, box, [0, 1], ([, y], v) =>\n v === 1 ? [0, 0] : [0, yc - y],\n );\n}\n\n/** The upper lash comes down onto the crease and flattens over the seam the\n * folded white leaves. A lash is drawn arched; shut, that arch would read\n * as a smile, so its middle comes down further than its ends. */\nexport function lashFold(\n param: string,\n mesh: IkiMesh,\n lash: Box,\n eye: Box,\n travel: number,\n): IkiWarp {\n const yc = eye.y1 - travel * bh(eye) - 0.04 * bh(eye);\n const c = cx(lash);\n const half = bw(lash) / 2;\n const sag = 0.3 * bh(lash);\n return localWarp(param, mesh, lash, [0, 1], ([x, y], v) => {\n if (v === 1) return [0, 0];\n const u = (x - c) / half;\n return [0, yc + (y - lash.y0) * 0.5 - sag * (1 - u * u) - y];\n });\n}\n\n/** Gaze: the iris (and pupil) travel within the white, a fraction of the\n * iris's own width; a highlight is a reflection and travels half as far. */\nexport function gazeBindings(irisW: number, share = 1): IkiBinding[] {\n const gx = AMPLITUDE.gazeX * irisW * share;\n const gy = AMPLITUDE.gazeY * irisW * share;\n return [\n {\n parameter: P.EyeballX,\n channel: \"translateX\",\n from: -round1(gx),\n to: round1(gx),\n },\n {\n parameter: P.EyeballY,\n channel: \"translateY\",\n from: -round1(gy),\n to: round1(gy),\n },\n ];\n}\n\nexport function gazeReach(irisW: number, share = 1): Vec {\n return [AMPLITUDE.gazeX * irisW * share, AMPLITUDE.gazeY * irisW * share];\n}\n\n// --- brows ----------------------------------------------------------------------\n\n/** How far a brow raises and lowers, px. */\nexport function browReach(hh: number): number {\n return AMPLITUDE.brow * hh;\n}\n\nexport function browBindings(side: \"L\" | \"R\", reach: number): IkiBinding[] {\n const y = side === \"L\" ? P.BrowLeftY : P.BrowRightY;\n const a = side === \"L\" ? P.BrowLeftAngle : P.BrowRightAngle;\n return [\n {\n parameter: y,\n channel: \"translateY\",\n from: -round1(reach),\n to: round1(reach),\n },\n { parameter: a, channel: \"rotate\", from: -BROW_TILT, to: BROW_TILT },\n ];\n}\nexport const BROW_TILT = 15;\n\n// --- mouth ----------------------------------------------------------------------\n\n/** Smile lifts the corners and widens the mouth a little; frown the reverse. */\nexport function mouthForm(mesh: IkiMesh, box: Box): IkiWarp {\n const a = 0.3 * bh(box);\n const c = cx(box);\n const half = bw(box) / 2;\n return localWarp(P.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {\n if (v === 0) return [0, 0];\n const u = (x - c) / half;\n const widen = v > 0 ? 0.05 : 0.03;\n return [v * widen * (x - c), v * a * (u * u - 0.3)];\n });\n}\n\n/** The open drawing grows out of the closed lips: shut, it is a line along\n * its own top lip; open, it is as wide as the profile's mouth gets. */\nexport function mouthOpenGrow(mesh: IkiMesh, box: Box): IkiWarp {\n const c = cx(box);\n return localWarp(P.MouthOpen, mesh, box, [0, 1], ([x, y], v) =>\n v === 1\n ? [(AMPLITUDE.mouthOpenWidth - 1) * (x - c), 0]\n : [0, box.y1 + (y - box.y1) * 0.2 - y],\n );\n}\n\n/** The closed lips widen as they open (and fade). */\nexport function mouthWiden(mesh: IkiMesh, box: Box): IkiWarp {\n const c = cx(box);\n return localWarp(P.MouthOpen, mesh, box, [0, 1], ([x], v) => [\n v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),\n 0,\n ]);\n}\n\n// --- hair -------------------------------------------------------------------------\n\n/** Root-pinned sway: the top of the layer stays, its ends swing `amp` px at\n * full sway. */\nexport function hairSway(\n param: string,\n mesh: IkiMesh,\n box: Box,\n amp: number,\n): IkiWarp {\n return localWarp(\n param,\n mesh,\n box,\n [-SWAY_RANGE, 0, SWAY_RANGE],\n ([, y], v) => {\n const t = Math.max(0, (box.y1 - y) / bh(box));\n return [(v / SWAY_RANGE) * amp * t ** SWAY_CURVE, 0];\n },\n );\n}\n\n/**\n * Hang under a roll: the head rotates about `pivot`; each vertex is turned\n * back by `weight(y, i)` of that — all of it for the neck, which stays on\n * its shoulders, some of it for long hair, which hangs rather than swinging\n * out like a board.\n */\nexport function tiltHang(\n mesh: IkiMesh,\n box: Box,\n pivot: Vec,\n weight: (y: number, i: number) => number,\n): IkiWarp {\n return localWarp(P.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {\n const g = weight(y, i);\n if (g === 0 || v === 0) return [0, 0];\n const a = -g * rollOf(v);\n const px = x - pivot[0];\n const py = y - pivot[1];\n return [\n pivot[0] + px * Math.cos(a) - py * Math.sin(a) - x,\n pivot[1] + px * Math.sin(a) + py * Math.cos(a) - y,\n ];\n });\n}\n\n/** Long hair's hang weight: none above the pivot, rising to HAIR_HANG at the\n * layer's bottom. */\nexport function hairHangWeight(\n pivotY: number,\n bottom: number,\n): (y: number) => number {\n // Hair that ends above the pivot (a fringe) hangs from nothing: it rolls\n // with the head.\n if (bottom >= pivotY) return () => 0;\n return (y) => HAIR_HANG * smoothstep(pivotY, bottom, y);\n}\n\nconst round1 = (v: number) => roundTo(v, 0.1);\n"],"mappings":"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","names":["import_format","deformers","y","x","span","x","import_format","import_format","P","import_format","rim","root","strand","P","xs","cols","rows","neck","b","top","land","g","turn","import_format","P","P"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/document.ts","../src/mesh-uv.ts","../src/commands.ts","../src/grid-keyform.ts","../src/reparent.ts","../src/alpha-bbox.ts","../src/layer-measure.ts","../src/binding-capture.ts","../src/atlas.ts","../src/factories.ts","../src/auto-rig/profile.ts","../src/auto-rig/types.ts","../src/auto-rig/roles.ts","../src/auto-rig/generate.ts","../src/auto-rig/animations.ts","../src/auto-rig/arms.ts","../src/auto-rig/body.ts","../src/auto-rig/layout.ts","../src/auto-rig/drivers.ts","../src/auto-rig/grid.ts","../src/auto-rig/checks.ts","../src/auto-rig/context.ts","../src/auto-rig/head.ts","../src/auto-rig/fields.ts","../src/auto-rig/face-mesh.ts","../src/auto-rig/solve.ts"],"sourcesContent":["export {\n EditorDocument,\n type AtlasAssignment,\n type ApplyAtlasInput,\n} from \"./document\";\nexport {\n AddDeformer,\n AddPart,\n AddPhysicsRig,\n CaptureGridKeyform,\n DeleteDeformer,\n DeletePart,\n DeletePhysicsRig,\n SetDeformerBindings,\n SetDeformerParent,\n SetDeformerPivot,\n SetDeformerPivotX,\n SetDeformerPivotY,\n SetDeformerTransform,\n SetPartBindings,\n SetPartColor,\n SetPartDeformer,\n SetPartMesh,\n SetPartHeight,\n SetPartOrder,\n SetPartTransform,\n SetPartWidth,\n SetPhysicsRig,\n type DeformerTransformChannel,\n type EditCommand,\n type EditTransformChannel,\n} from \"./commands\";\nexport {\n ALPHA_BBOX_THRESHOLD,\n detectAlphaBbox,\n type AlphaBbox,\n} from \"./alpha-bbox\";\nexport {\n ALPHA_OPAQUE,\n HEAD_BAND,\n SPECK_CORE_FRACTION,\n createLayerSetMeasurer,\n denseCoreOf,\n foregroundSpan,\n headHalfOf,\n isSpeckCore,\n type LayerSetMeasurement,\n type LayerSetMeasurer,\n type RgbaLayer,\n} from \"./layer-measure\";\nexport { captureBindingEndpoint } from \"./binding-capture\";\nexport {\n computeGridOffsets,\n interpolateGridOffsets,\n upsertGridKeyform,\n} from \"./grid-keyform\";\nexport {\n packAtlas,\n uvRectFor,\n ATLAS_PADDING,\n UV_INSET_PX,\n type AtlasSource,\n type AtlasPlacement,\n type AtlasLayout,\n} from \"./atlas\";\nexport {\n validateDeformerDelete,\n validateDeformerReparent,\n validatePartAttach,\n} from \"./reparent\";\nexport {\n createDefaultPart,\n createDefaultMatrixDeformer,\n createDefaultWarpDeformer,\n createGridMesh,\n} from \"./factories\";\nexport {\n DEFAULT_TURN_TARGETS,\n LayerGeometryError,\n TurnTargetError,\n generateIkiFromLayerSet,\n parseLayerRoles,\n partIdsOfRole,\n type IrisStrand,\n type LayerInput,\n type RigStyle,\n type StrandOverlap,\n type TurnDepths,\n type TurnSolveReport,\n type TurnTargets,\n} from \"./auto-rig\";\n","import { parseIkiModel } from \"@ikijs/format\";\nimport type {\n IkiBinding,\n IkiDeformer,\n IkiDeformerBinding,\n IkiDeformerTransform,\n IkiMatrixDeformer,\n IkiModel,\n IkiPart,\n IkiPhysics,\n IkiTexture,\n IkiTransform,\n IkiUvRect,\n IkiWarpDeformer,\n} from \"@ikijs/format\";\n\nimport type { EditCommand } from \"./commands\";\nimport { remapMeshUvsToRect } from \"./mesh-uv\";\n\n/**\n * One part mapped to an imported atlas source. `index` is always 0 because the\n * atlas is a single page; only the `uv` sub-rectangle varies per part.\n */\nexport interface AtlasAssignment {\n partId: string;\n uv: IkiUvRect;\n}\n\n/** Input to {@link EditorDocument.applyAtlas}: the new atlas table plus the\n * per-part UV assignments into it. */\nexport interface ApplyAtlasInput {\n textures: IkiTexture[];\n partTextureAssignments: AtlasAssignment[];\n}\n\n/**\n * In-memory editing session over a single {@link IkiModel}. The model is held\n * directly (no superset) and mutated in place by invertible {@link EditCommand}s\n * pushed through {@link execute}; undo/redo invert/re-apply them.\n *\n * The constructor `structuredClone`s the input so the caller's model is never\n * mutated. Parts are addressed by stable `id`, never by array index.\n */\nexport class EditorDocument {\n private readonly model: IkiModel;\n private readonly undoStack: EditCommand[] = [];\n private readonly redoStack: EditCommand[] = [];\n /** Editor-only session state, never serialized; keyed by stable part id. The\n * unmodified BASE local uvs of every mesh part, captured once at construction\n * so atlas remaps always derive from the original (idempotent). */\n private readonly baseMeshUvs = new Map<string, number[]>();\n\n constructor(model: IkiModel) {\n this.model = structuredClone(model);\n // Capture-once base UVs. Scope: assumes the loaded model's mesh parts carry\n // original LOCAL 0..1 uvs (true for the sample). Restoring base UVs after\n // reloading an already-textured exported model is out of scope (deferred —\n // needs project-file persistence).\n for (const part of this.model.parts) {\n if (part.mesh) {\n this.baseMeshUvs.set(part.id, part.mesh.uvs.slice());\n }\n }\n }\n\n /** Live reference to the working model — for READ access. Mutate it only\n * through {@link execute}/{@link undo}/{@link redo}. */\n getModel(): IkiModel {\n return this.model;\n }\n\n /** Resolve a part by stable id. Throws a plain `Error` (NOT an\n * `IkiFormatError`) with a path-qualified message if the id is unknown. */\n findPart(id: string): IkiPart {\n const part = this.model.parts.find((p) => p.id === id);\n if (!part) {\n throw new Error(`parts: no part with id \"${id}\"`);\n }\n return part;\n }\n\n /** Resolve a warp deformer by stable id. Throws a path-qualified plain\n * `Error` if no deformer matches the id or the match is not a warp deformer.\n * READ/mutate-through accessor, consistent with {@link findPart}. */\n findWarpDeformer(id: string): IkiWarpDeformer {\n const deformer = this.model.deformers?.find((d) => d.id === id);\n if (!deformer || deformer.kind !== \"warp\") {\n throw new Error(`deformers: no warp deformer with id \"${id}\"`);\n }\n return deformer;\n }\n\n /** Resolve a matrix deformer by stable id. Throws a path-qualified plain\n * `Error` if no deformer matches the id or the match is a warp deformer\n * (`kind === \"warp\"`). A `kind` of `\"matrix\"` or `undefined` is a matrix\n * deformer. READ/mutate-through accessor, consistent with {@link findPart}. */\n findMatrixDeformer(id: string): IkiMatrixDeformer {\n const deformer = this.model.deformers?.find((d) => d.id === id);\n if (!deformer || deformer.kind === \"warp\") {\n throw new Error(`deformers: no matrix deformer with id \"${id}\"`);\n }\n return deformer;\n }\n\n /** Resolve any deformer (matrix or warp) by stable id. Throws a\n * path-qualified plain `Error` if no deformer matches the id.\n * READ/mutate-through accessor, consistent with {@link findPart}. */\n findDeformer(id: string): IkiDeformer {\n const deformer = this.model.deformers?.find((d) => d.id === id);\n if (!deformer) {\n throw new Error(`deformers: no deformer with id \"${id}\"`);\n }\n return deformer;\n }\n\n /** Resolve a physics rig by stable id. Throws a path-qualified plain `Error`\n * if no rig matches the id. The `physics` array is optional, so guard it.\n * READ/mutate-through accessor, consistent with {@link findDeformer}. */\n findPhysicsRig(id: string): IkiPhysics {\n const rig = this.model.physics?.find((r) => r.id === id);\n if (!rig) {\n throw new Error(`physics: no physics rig with id \"${id}\"`);\n }\n return rig;\n }\n\n /**\n * Record the base mesh UVs for a part inserted AFTER construction (e.g. by\n * {@link AddPart}). Returns the PRIOR entry for that id (or `undefined` if\n * none existed) so the caller can restore it on undo. No-op for meshless\n * parts (returns `undefined`). Must be called by any command that pushes a\n * mesh part into the model so the part joins the constructor-captured base-UV\n * side state required by {@link applyAtlas}.\n *\n * The returned prior value is what {@link restoreBaseMeshUvs} expects on\n * undo — pass it verbatim. Hazard guarded: DeletePart(X) → AddPart(X′) →\n * undo(add) → undo(delete); without restore, X's constructor-captured entry\n * would be permanently gone after undo of the add, causing applyAtlas to\n * fail when X is restored.\n */\n captureBaseMeshUvs(partId: string): number[] | undefined {\n const prev = this.baseMeshUvs.get(partId);\n const part = this.model.parts.find((p) => p.id === partId);\n if (part?.mesh) {\n this.baseMeshUvs.set(partId, part.mesh.uvs.slice());\n }\n return prev;\n }\n\n /**\n * Restore the base-UV side state to exactly what it was before a\n * {@link captureBaseMeshUvs} call. Called from {@link AddPart.invert}:\n * pass the value returned by captureBaseMeshUvs on first apply.\n * - `prev` is `number[]` → sets the entry (restores a prior mesh's base).\n * - `prev` is `undefined` → deletes the entry (no entry existed before the\n * add, so a later different-mesh part reusing the id must not inherit this\n * one's base).\n * DeletePart does NOT call this — the entry persists across delete/undo so\n * the restored part still has its base available for applyAtlas.\n */\n restoreBaseMeshUvs(partId: string, prev: number[] | undefined): void {\n if (prev !== undefined) {\n this.baseMeshUvs.set(partId, prev);\n } else {\n this.baseMeshUvs.delete(partId);\n }\n }\n\n /** The construction-captured base UVs for a mesh part. Throws a path-qualified\n * plain `Error` if absent. SINGLE accessor for both apply branches — never\n * read `baseMeshUvs` with a bare `!` elsewhere. */\n private requireBaseUvs(partId: string): number[] {\n const base = this.baseMeshUvs.get(partId);\n if (!base) {\n throw new Error(`parts: no base mesh uvs captured for part \"${partId}\"`);\n }\n return base;\n }\n\n /**\n * Replace the atlas table and rewrite every part's texture reference in a\n * single atomic step. For every part in `partTextureAssignments` set\n * `texture = { index: 0, uv }`; CLEAR `texture` (delete the key) on every\n * other part.\n *\n * Mesh parts are textured as a MATCHED PAIR: an assigned mesh part also has\n * its per-vertex `mesh.uvs` remapped (from the construction-captured base)\n * into the same `uv` rect; an unassigned mesh part has its `mesh.uvs` restored\n * to that base. Quad parts carry `texture.uv` only and are untouched here.\n *\n * Deliberately NON-undoable: it does NOT push to or clear the undo/redo\n * stacks (texture/atlas state is not undoable in 5b — the unified\n * editor-state superset is deferred to 5d). `canUndo()`/`canRedo()` are\n * unchanged after a call.\n *\n * Validate-all-then-apply: structural input validation, per-partId\n * resolution, and a base-UV preflight over every mesh part all run BEFORE any\n * mutation, so a bad input (wrong shape, duplicate partId, unknown partId, or\n * a mesh part with no captured base) throws a plain `Error` and leaves the\n * model exactly as it was — never a partial application.\n */\n applyAtlas(input: ApplyAtlasInput): void {\n // Step A — structural validation of the input shape.\n const { texture, assignmentsByPart } = this.normalizeAtlasInput(input);\n\n // Step B — resolve every partId before mutating anything.\n const resolved = new Map<IkiPart, IkiUvRect>();\n for (const [partId, uv] of assignmentsByPart) {\n resolved.set(this.findPart(partId), uv);\n }\n\n // Step C — preflight base UVs for EVERY mesh part (assigned AND unassigned):\n // the mutate loop's clear/restore branch also reads the base of unassigned\n // mesh parts, so this guard must cover them before any write so atomicity\n // (validate-all-then-apply) holds.\n for (const part of this.model.parts) {\n if (part.mesh) {\n this.requireBaseUvs(part.id);\n }\n }\n\n // Mutate — only reached when A + B + C all pass.\n this.model.textures =\n texture === undefined ? undefined : [{ source: texture.source }];\n for (const part of this.model.parts) {\n const uv = resolved.get(part);\n if (uv) {\n part.texture = {\n index: 0,\n uv: { x: uv.x, y: uv.y, width: uv.width, height: uv.height },\n };\n if (part.mesh) {\n // Replace the mesh object so each part owns its own uvs array —\n // de-aliases parts that shared the same mesh object in the input model.\n part.mesh = {\n ...part.mesh,\n uvs: remapMeshUvsToRect(this.requireBaseUvs(part.id), uv),\n };\n }\n } else {\n delete part.texture;\n if (part.mesh) {\n // Same spread here to break aliasing on restore as well.\n part.mesh = {\n ...part.mesh,\n uvs: this.requireBaseUvs(part.id).slice(),\n };\n }\n }\n }\n }\n\n /**\n * Clear a model-committed texture reference from a single part. Deliberately\n * NON-undoable, matching {@link applyAtlas} — texture/atlas state is not in\n * the undo model (unified editor-state is deferred). Does NOT push to or\n * clear the undo/redo stacks. Does NOT touch `mesh.uvs` — atlas-space UVs on\n * an untextured mesh are inert for color rendering; a later atlas import\n * remaps from the base UVs anyway.\n *\n * This is the single consistent texture/atlas undo boundary: by the time a\n * part is deletable (no texture), its DeletePart snapshot carries no texture\n * reference, so no stale index can resurface on undo after a later atlas\n * repack.\n *\n * Throws a path-qualified plain `Error` (NOT `IkiFormatError`) if the part\n * id is unknown — same contract as {@link findPart}.\n */\n clearPartTextureRef(partId: string): void {\n const part = this.findPart(partId);\n delete part.texture;\n }\n\n /**\n * Validate the structural shape of an {@link ApplyAtlasInput} without\n * touching the model, returning a known-good `{ texture?, assignmentsByPart }`\n * for {@link applyAtlas} to resolve and apply.\n */\n private normalizeAtlasInput(input: ApplyAtlasInput): {\n texture?: IkiTexture;\n assignmentsByPart: Map<string, IkiUvRect>;\n } {\n if (input.textures.length > 1) {\n throw new Error(\n `applyAtlas: textures must be a single atlas page (got ${input.textures.length})`,\n );\n }\n if (\n input.partTextureAssignments.length > 0 &&\n input.textures.length !== 1\n ) {\n throw new Error(\n \"applyAtlas: partTextureAssignments require exactly one texture\",\n );\n }\n\n const assignmentsByPart = new Map<string, IkiUvRect>();\n for (const { partId, uv } of input.partTextureAssignments) {\n if (assignmentsByPart.has(partId)) {\n throw new Error(\n `applyAtlas: duplicate partId \"${partId}\" in partTextureAssignments`,\n );\n }\n assignmentsByPart.set(partId, uv);\n }\n\n return { texture: input.textures[0], assignmentsByPart };\n }\n\n /**\n * Overwrite a part's whole transform with a fresh copy of `transform`.\n * Replacing the whole object (rather than individual channels) preserves any\n * optional keys already absent from the incoming value.\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * pose. Does NOT push to or clear undoStack/redoStack (sibling to\n * {@link applyAtlas}'s non-undoable boundary). The caller is responsible for\n * restoring the exact prior snapshot when the capture pose ends.\n *\n * `IkiTransform` is a flat number map, so a shallow spread is a sufficient\n * deep copy — no aliasing of the caller's object remains.\n */\n setPartTransformEphemeral(partId: string, transform: IkiTransform): void {\n const part = this.findPart(partId);\n part.transform = { ...transform };\n }\n\n /**\n * Overwrite a matrix deformer's optional transform with a fresh copy, or\n * delete it when `transform` is `undefined`.\n * `undefined` deletes the key, restoring the deformer to the same state as\n * one that never had a transform (absent-vs-present matters for downstream\n * renderers).\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * pose. Does NOT push to or clear undoStack/redoStack (sibling to\n * {@link applyAtlas}'s non-undoable boundary). The caller is responsible for\n * restoring the exact prior snapshot when the capture pose ends.\n *\n * `IkiDeformerTransform` is a flat number map, so a shallow spread is a\n * sufficient deep copy — no aliasing of the caller's object remains.\n */\n setDeformerTransformEphemeral(\n deformerId: string,\n transform: IkiDeformerTransform | undefined,\n ): void {\n const deformer = this.findMatrixDeformer(deformerId);\n if (transform === undefined) {\n delete deformer.transform;\n } else {\n deformer.transform = { ...transform };\n }\n }\n\n /**\n * Overwrite a part's whole bindings array with a fresh deep copy, or delete\n * the key when `bindings` is empty.\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * neutralization (zeroing the row being recaptured so the preview reflects\n * base-only during posing). Does NOT push to or clear undoStack/redoStack.\n * The caller is responsible for restoring the original bindings when the\n * capture session ends.\n */\n setPartBindingsEphemeral(partId: string, bindings: IkiBinding[]): void {\n const part = this.findPart(partId);\n if (bindings.length > 0) {\n part.bindings = bindings.map((b) => ({ ...b }));\n } else {\n delete part.bindings;\n }\n }\n\n /**\n * Overwrite a matrix deformer's whole bindings array with a fresh deep copy,\n * or delete the key when `bindings` is empty.\n *\n * Deliberately NON-undoable — used ONLY for an editor app's transient capture\n * neutralization (zeroing the row being recaptured so the preview reflects\n * base-only during posing). Does NOT push to or clear undoStack/redoStack.\n * The caller is responsible for restoring the original bindings when the\n * capture session ends.\n */\n setDeformerBindingsEphemeral(\n deformerId: string,\n bindings: IkiDeformerBinding[],\n ): void {\n const deformer = this.findMatrixDeformer(deformerId);\n if (bindings.length > 0) {\n deformer.bindings = bindings.map((b) => ({ ...b }));\n } else {\n delete deformer.bindings;\n }\n }\n\n /** Apply a command and record it as one undo step. Clears the redo stack. */\n execute(cmd: EditCommand): void {\n cmd.apply(this);\n this.undoStack.push(cmd);\n this.redoStack.length = 0;\n }\n\n /** Invert the most recent command and move it onto the redo stack. */\n undo(): void {\n const cmd = this.undoStack.pop();\n if (!cmd) return;\n cmd.invert(this);\n this.redoStack.push(cmd);\n }\n\n /** Re-apply the most recently undone command and move it back onto undo. */\n redo(): void {\n const cmd = this.redoStack.pop();\n if (!cmd) return;\n cmd.apply(this);\n this.undoStack.push(cmd);\n }\n\n canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n /**\n * Validate and export the current working model by running it through\n * {@link parseIkiModel}. Uses `structuredClone` so the validator's\n * normalized output cannot alias the working model. Propagates\n * `IkiFormatError` unchanged on failure — callers surface `.message`.\n */\n toIkiModel(): IkiModel {\n return parseIkiModel(structuredClone(this.model));\n }\n\n /**\n * Pretty-print the validated model as a `.iki` JSON string. Always\n * validates first — invalid documents never reach a file.\n */\n serialize(): string {\n return JSON.stringify(this.toIkiModel(), null, 2);\n }\n}\n","import type { IkiUvRect } from \"@ikijs/format\";\n\n/**\n * Affinely map a mesh's BASE local UVs into an atlas sub-rectangle.\n *\n * Per the `@ikijs/format` UV convention (top-left origin, +y down, 0..1; see\n * {@link IkiUvRect}/{@link IkiMesh}), the input is the part's BASE local uvs and\n * the output places each component into `rect` with NO flip — base UV space and\n * `rect` share the same orientation:\n * out[2i] = rect.x + baseUvs[2i] * rect.width\n * out[2i+1] = rect.y + baseUvs[2i+1] * rect.height\n *\n * The caller guarantees `rect` is inset/clamped (via `uvRectFor`) so every\n * output component stays within 0..1 and passes the format validator.\n *\n * Returns a fresh array; `baseUvs` is never mutated.\n */\nexport function remapMeshUvsToRect(\n baseUvs: number[],\n rect: IkiUvRect,\n): number[] {\n if (baseUvs.length % 2 !== 0) {\n throw new Error(\n `remapMeshUvsToRect: baseUvs must have an even length (u,v pairs), got ${baseUvs.length}`,\n );\n }\n\n const out = new Array<number>(baseUvs.length);\n for (let i = 0; i < baseUvs.length; i += 2) {\n out[i] = rect.x + baseUvs[i] * rect.width;\n out[i + 1] = rect.y + baseUvs[i + 1] * rect.height;\n }\n return out;\n}\n","import type {\n IkiBinding,\n IkiDeformer,\n IkiDeformerBinding,\n IkiDeformerTransform,\n IkiGridKeyform,\n IkiMatrixDeformer,\n IkiMesh,\n IkiModel,\n IkiPart,\n IkiPhysics,\n} from \"@ikijs/format\";\nimport {\n IKI_FORMAT_VERSION,\n IkiFormatError,\n parseIkiModel,\n} from \"@ikijs/format\";\n\nimport type { EditorDocument } from \"./document\";\nimport { upsertGridKeyform } from \"./grid-keyform\";\nimport { remapMeshUvsToRect } from \"./mesh-uv\";\nimport {\n validateDeformerDelete,\n validateDeformerReparent,\n validatePartAttach,\n} from \"./reparent\";\n\n/**\n * Scan the id-flat namespace (parts first, then deformers) and return which\n * array already holds `id`, or `undefined` if the id is free. Parts and\n * deformers share a single flat id namespace, so both arrays must be checked\n * to produce a source-qualified collision message.\n */\nfunction findIdCollision(\n model: IkiModel,\n id: string,\n): \"part\" | \"deformer\" | undefined {\n for (const p of model.parts) {\n if (p.id === id) return \"part\";\n }\n for (const d of model.deformers ?? []) {\n if (d.id === id) return \"deformer\";\n }\n return undefined;\n}\n\n/**\n * One invertible edit. The document is passed IN at apply/invert time — a\n * command is constructed from `(partId, value)` alone, before any document\n * exists — so the same command object can be applied, inverted, and re-applied\n * by the undo/redo stack.\n *\n * Prior-value capture happens exactly ONCE, on the first {@link apply}. `redo`\n * (a second `apply`) reuses that captured value rather than re-reading the\n * current field, so undo always restores the original target.\n */\nexport interface EditCommand {\n apply(doc: EditorDocument): void;\n invert(doc: EditorDocument): void;\n readonly label: string;\n}\n\n/** Channels of {@link IkiTransform} this editor can edit (object-field names,\n * NOT the binding `IkiTransformChannel` vocabulary). */\nexport type EditTransformChannel =\n | \"x\"\n | \"y\"\n | \"rotation\"\n | \"scaleX\"\n | \"scaleY\"\n | \"opacity\";\n\n/**\n * Generic single-field command: reads/writes one field of the resolved part via\n * a getter/setter closure, capturing the prior value on the first `apply` and\n * restoring it on `invert`. `T` is the captured value's type; for cloned values\n * (the color tuple) the getter/setter perform the copy.\n */\nclass FieldCommand<T> implements EditCommand {\n readonly label: string;\n private captured = false;\n private prevValue!: T;\n\n constructor(\n private readonly partId: string,\n private readonly newValue: T,\n label: string,\n private readonly get: (part: IkiPart) => T,\n private readonly set: (part: IkiPart, value: T) => void,\n ) {\n this.label = label;\n }\n\n apply(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n if (!this.captured) {\n this.prevValue = this.get(part);\n this.captured = true;\n }\n this.set(part, this.newValue);\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n this.set(part, this.prevValue);\n }\n}\n\n/** Edit a part's RGBA fill. The 4-tuple is mutable, so the command clones on\n * construction (caller's array), on capture (part's current color), and on\n * assign (writing to the part) — it never retains the caller's or model's\n * array by reference. */\nexport class SetPartColor extends FieldCommand<\n [number, number, number, number]\n> {\n constructor(partId: string, rgba: [number, number, number, number]) {\n super(\n partId,\n [...rgba] as [number, number, number, number],\n \"Set color\",\n (part) => [...part.color],\n (part, value) => {\n part.color = [...value] as [number, number, number, number];\n },\n );\n }\n}\n\n/** Edit a part's width (model-space units). */\nexport class SetPartWidth extends FieldCommand<number> {\n constructor(partId: string, value: number) {\n super(\n partId,\n value,\n \"Set width\",\n (part) => part.width,\n (part, v) => {\n part.width = v;\n },\n );\n }\n}\n\n/** Edit a part's height (model-space units). */\nexport class SetPartHeight extends FieldCommand<number> {\n constructor(partId: string, value: number) {\n super(\n partId,\n value,\n \"Set height\",\n (part) => part.height,\n (part, v) => {\n part.height = v;\n },\n );\n }\n}\n\n/** Edit a part's paint order. */\nexport class SetPartOrder extends FieldCommand<number> {\n constructor(partId: string, value: number) {\n super(\n partId,\n value,\n \"Set order\",\n (part) => part.order,\n (part, v) => {\n part.order = v;\n },\n );\n }\n}\n\n/**\n * Edit one channel of a part's base transform. `x`/`y` are required; the rest\n * are optional and may be absent on the part. For an optional channel the\n * command captures the raw current value INCLUDING `undefined`, and restoring\n * `undefined` DELETES the key so undo returns the part to its original\n * (possibly-omitted) shape. Engine defaults (rotation 0 / scale 1 / opacity 1)\n * are NOT substituted here.\n */\nexport class SetPartTransform extends FieldCommand<number | undefined> {\n constructor(partId: string, channel: EditTransformChannel, value: number) {\n super(\n partId,\n value,\n \"Set transform\",\n (part) => part.transform[channel],\n (part, v) => {\n if (v === undefined) {\n delete part.transform[channel];\n } else {\n part.transform[channel] = v;\n }\n },\n );\n }\n}\n\n/**\n * Capture the warp deformer's grid as one keyform at the driving parameter\n * `value`, upserting `offsets` into the deformer's single grid warp. The 4-tuple-style\n * mutable `offsets` array is cloned on construction so a later caller mutation\n * cannot corrupt apply/redo (mirrors {@link SetPartColor}).\n *\n * `apply` validates BEFORE mutating: the deformer must have exactly one grid\n * warp (several are refused — which driver to write into is ambiguous), the\n * offsets length must equal `grid.points.length`, and `value` must lie within\n * the driving parameter's declared `[min,max]` (fail fast, before\n * `parseIkiModel` would reject it). Prior keyforms are deep-copied once on the\n * first `apply` (capture-once like {@link FieldCommand}); `invert` restores\n * that deep copy so re-apply after undo never aliases.\n */\nexport class CaptureGridKeyform implements EditCommand {\n readonly label = \"Capture grid keyform\";\n private readonly offsets: number[];\n private captured = false;\n private prevKeyforms!: IkiGridKeyform[];\n\n constructor(\n private readonly deformerId: string,\n private readonly value: number,\n offsets: number[],\n ) {\n this.offsets = [...offsets];\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findWarpDeformer(this.deformerId);\n const count = deformer.warps?.length ?? 0;\n if (count > 1) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps: ${count} grid warps — capture targets a deformer with exactly one grid warp (which entry to write into is ambiguous)`,\n );\n }\n const warp = deformer.warps?.[0];\n if (!warp) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps: no grid warp to capture into`,\n );\n }\n if (this.offsets.length !== deformer.grid.points.length) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps[0].keyforms.offsets length ${this.offsets.length} must equal grid.points length ${deformer.grid.points.length}`,\n );\n }\n const param = doc\n .getModel()\n .parameters.find((p) => p.id === warp.parameter);\n if (!param) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps[0].parameter \"${warp.parameter}\" is not a declared parameter`,\n );\n }\n if (this.value < param.min || this.value > param.max) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps[0].keyforms.value ${this.value} is outside parameter \"${warp.parameter}\" range [${param.min},${param.max}]`,\n );\n }\n\n if (!this.captured) {\n this.prevKeyforms = structuredClone(warp.keyforms);\n this.captured = true;\n }\n warp.keyforms = upsertGridKeyform(warp.keyforms, this.value, [\n ...this.offsets,\n ]);\n }\n\n invert(doc: EditorDocument): void {\n const warp = doc.findWarpDeformer(this.deformerId).warps?.[0];\n if (!warp) {\n throw new Error(\n `deformers.\"${this.deformerId}\".warps: no grid warp to restore into`,\n );\n }\n warp.keyforms = structuredClone(this.prevKeyforms);\n }\n}\n\n/**\n * Generic single-field command targeting a matrix deformer, mirroring\n * {@link FieldCommand} but resolving via `doc.findMatrixDeformer` instead of\n * `doc.findPart`. Capture-once on first `apply`; restore on `invert`.\n */\nclass DeformerFieldCommand<T> implements EditCommand {\n readonly label: string;\n private captured = false;\n private prevValue!: T;\n\n constructor(\n private readonly deformerId: string,\n private readonly newValue: T,\n label: string,\n private readonly get: (deformer: IkiMatrixDeformer) => T,\n private readonly set: (deformer: IkiMatrixDeformer, value: T) => void,\n ) {\n this.label = label;\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (!this.captured) {\n this.prevValue = this.get(deformer);\n this.captured = true;\n }\n this.set(deformer, this.newValue);\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n this.set(deformer, this.prevValue);\n }\n}\n\n/** Edit a matrix deformer's pivot x. */\nexport class SetDeformerPivotX extends DeformerFieldCommand<number> {\n constructor(deformerId: string, value: number) {\n super(\n deformerId,\n value,\n \"Set pivot x\",\n (d) => d.pivot.x,\n (d, v) => {\n d.pivot.x = v;\n },\n );\n }\n}\n\n/** Edit a matrix deformer's pivot y. */\nexport class SetDeformerPivotY extends DeformerFieldCommand<number> {\n constructor(deformerId: string, value: number) {\n super(\n deformerId,\n value,\n \"Set pivot y\",\n (d) => d.pivot.y,\n (d, v) => {\n d.pivot.y = v;\n },\n );\n }\n}\n\n/**\n * Set a matrix deformer's pivot x and y atomically (one drag = one undo step).\n * {@link SetDeformerPivotX} and {@link SetDeformerPivotY} remain for the\n * Inspector's single-axis number inputs.\n */\nexport class SetDeformerPivot implements EditCommand {\n readonly label = \"Set pivot\";\n private captured = false;\n private prevPivot!: { x: number; y: number };\n private readonly pivot: { x: number; y: number };\n\n constructor(\n private readonly deformerId: string,\n pivot: { x: number; y: number },\n ) {\n // Fresh clone so a caller mutating their arg after construction cannot\n // corrupt apply/redo.\n this.pivot = { x: pivot.x, y: pivot.y };\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (!this.captured) {\n this.prevPivot = { x: deformer.pivot.x, y: deformer.pivot.y };\n this.captured = true;\n }\n deformer.pivot = { x: this.pivot.x, y: this.pivot.y };\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n // Fresh clone — never alias the captured object so repeated undo/redo\n // cycles cannot corrupt the saved prior value.\n deformer.pivot = { x: this.prevPivot.x, y: this.prevPivot.y };\n }\n}\n\n/** Channels of {@link IkiDeformerTransform} this editor can edit. */\nexport type DeformerTransformChannel =\n | \"x\"\n | \"y\"\n | \"rotation\"\n | \"scaleX\"\n | \"scaleY\";\n\n/**\n * Edit one channel of a matrix deformer's base transform. Because\n * {@link IkiDeformerTransform} REQUIRES finite `x` and `y`, this command\n * captures and restores the WHOLE prior `transform` object (present or absent)\n * rather than a single channel, so undo can delete the transform when it did\n * not previously exist, and redo never produces a partial object missing `x`/`y`.\n *\n * When no `transform` is present on the deformer, `apply` creates one from\n * the identity base `{ x: 0, y: 0 }` — the minimal valid shape the validator\n * accepts — then writes the edited channel. For example, editing `rotation`\n * on a transform-less deformer yields `{ x: 0, y: 0, rotation: <value> }`.\n */\nexport class SetDeformerTransform implements EditCommand {\n readonly label = \"Set deformer transform\";\n private captured = false;\n private prevTransform!: IkiDeformerTransform | undefined;\n\n constructor(\n private readonly deformerId: string,\n private readonly channel: DeformerTransformChannel,\n private readonly value: number,\n ) {}\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (!this.captured) {\n // Shallow clone is sufficient — IkiDeformerTransform is a flat number map.\n this.prevTransform =\n deformer.transform === undefined\n ? undefined\n : { ...deformer.transform };\n this.captured = true;\n }\n // Start from the existing transform or the identity base. The identity base\n // is { x: 0, y: 0 } because the validator unconditionally requires finite\n // x and y whenever a transform object is present.\n const next: IkiDeformerTransform = {\n ...(deformer.transform ?? { x: 0, y: 0 }),\n };\n next[this.channel] = this.value;\n deformer.transform = next;\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (this.prevTransform === undefined) {\n delete deformer.transform;\n } else {\n // Assign a fresh clone — never alias the captured object so repeated\n // undo/redo cycles cannot corrupt the saved prior value.\n deformer.transform = { ...this.prevTransform };\n }\n }\n}\n\n/**\n * Replace a matrix deformer's `bindings` array wholesale. A single command\n * covers add, edit, and remove (pass the desired final array; pass `[]` to\n * remove all). Mirrors {@link CaptureGridKeyform}'s deep-copy discipline:\n * clone-on-construction, capture-once, fresh deep copy on invert.\n *\n * Each {@link IkiDeformerBinding} is a flat object so a per-element spread\n * `{ ...b }` is a sufficient deep copy.\n */\nexport class SetDeformerBindings implements EditCommand {\n readonly label = \"Set deformer bindings\";\n private readonly bindings: IkiDeformerBinding[];\n private captured = false;\n private prevBindings!: IkiDeformerBinding[] | undefined;\n\n constructor(\n private readonly deformerId: string,\n bindings: IkiDeformerBinding[],\n ) {\n // Clone the caller's array on construction — prevents post-execute mutation\n // of the caller's array from corrupting apply/redo.\n this.bindings = bindings.map((b) => ({ ...b }));\n }\n\n apply(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n\n // Validate a NARROW synthetic candidate before capture/mutate, exactly as\n // {@link SetPartBindings} does and for the same reason: a full\n // structuredClone(doc.getModel()) would also validate parts and deformers\n // the user is not editing, and those routinely hold in-flight `NaN` from an\n // emptied numeric input — so an unrelated blank field would refuse this\n // edit, and report it against the wrong object. The Inspector offers every\n // parameter in the model, so an undeclared id, a non-finite endpoint, or a\n // non-matrix channel must still be caught here.\n //\n // NOT covered by this shape: a binding that feeds a physics chain's own\n // anchor. That rule needs the whole deformer hierarchy, and reproducing it\n // over a sanitized model would mean hand-maintaining a second model shape\n // beside the validator. It stays an export-time check in `toIkiModel()`.\n // Parts and deformers share one flat id namespace, so the two synthetic\n // objects below must not both be \"_\".\n const candidateDeformer: Record<string, unknown> = {\n kind: \"matrix\",\n id: \"_d\",\n pivot: { x: 0, y: 0 },\n };\n if (this.bindings.length > 0) {\n candidateDeformer.bindings = this.bindings.map((b) => ({ ...b }));\n }\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [\n {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n },\n ],\n deformers: [candidateDeformer],\n };\n // The synthetic deformer is always at deformers[0]; rewrite that prefix so\n // the surfaced error names the real target.\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n throw new IkiFormatError(\n e.message.replace(\n /^deformers\\[0\\]/,\n `deformers.\"${this.deformerId}\"`,\n ),\n );\n }\n throw e;\n }\n\n if (!this.captured) {\n // Preserve the original absent-vs-empty distinction.\n this.prevBindings =\n deformer.bindings === undefined\n ? undefined\n : deformer.bindings.map((b) => ({ ...b }));\n this.captured = true;\n }\n if (this.bindings.length > 0) {\n // Assign a fresh deep copy — model must never alias the command's stored array.\n deformer.bindings = this.bindings.map((b) => ({ ...b }));\n } else {\n // Delete the key on empty: keeps the model shape minimal and correctly\n // represents \"no bindings\" as an absent key rather than an empty array.\n delete deformer.bindings;\n }\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findMatrixDeformer(this.deformerId);\n if (this.prevBindings === undefined) {\n delete deformer.bindings;\n } else {\n // Assign a fresh deep copy — never alias the captured array so re-apply\n // after undo cannot corrupt the saved prior value.\n deformer.bindings = this.prevBindings.map((b) => ({ ...b }));\n }\n }\n}\n\n/**\n * Reparent a deformer (matrix or warp) under a new parent, or promote it to\n * root (`newParentId === undefined`). Calls {@link validateDeformerReparent}\n * FIRST so invalid reparents (cycles, warp-under-warp, a pivot outside the new\n * warp parent's grid, unknown id) throw before any\n * capture or mutation — a throwing apply leaves the model and undo stack\n * untouched.\n *\n * Absent-vs-present distinction: captures both the prior `parent` value AND\n * whether the key was present on the object, so `invert` can delete the key\n * (restore \"absent\") rather than blindly assigning `undefined`.\n */\nexport class SetDeformerParent implements EditCommand {\n readonly label = \"Set deformer parent\";\n private captured = false;\n private prevParent: string | undefined = undefined;\n private prevHadParent = false;\n\n constructor(\n private readonly deformerId: string,\n private readonly newParentId: string | undefined,\n ) {}\n\n apply(doc: EditorDocument): void {\n // Validate FIRST — throws before capture/mutate on any violation.\n validateDeformerReparent(\n doc.getModel().deformers ?? [],\n this.deformerId,\n this.newParentId,\n );\n\n // A new ANCESTOR can still bind a parameter that a physics chain anchored\n // here emits, which the format rejects as feedback. That rule needs the\n // whole hierarchy, and validating a full clone of the document here refuses\n // the edit whenever any unrelated part or deformer holds in-flight `NaN`\n // from an emptied numeric input — reporting it against the wrong object.\n // So the feedback case stays an export-time check in `toIkiModel()`, where\n // it was before, rather than trading a rare corruption for a common block.\n //\n // Known cost of that trade: the host surfaces the export error (the editor\n // app re-exports on a ~200ms debounce), but the message names the CHAIN, not\n // the edit — reparent `headDeformer` and you get\n // `physicsChains[0].segments[1].output.parameter \"...\" feeds its own anchor\n // deformer chain (feedback)`, which reads as a complaint about a hair lock.\n // If a friendlier error surface ever lands, this is the message to special-case.\n const deformer = doc.findDeformer(this.deformerId);\n if (!this.captured) {\n this.prevHadParent = Object.prototype.hasOwnProperty.call(\n deformer,\n \"parent\",\n );\n this.prevParent = deformer.parent;\n this.captured = true;\n }\n if (this.newParentId !== undefined) {\n deformer.parent = this.newParentId;\n } else {\n delete deformer.parent;\n }\n }\n\n invert(doc: EditorDocument): void {\n const deformer = doc.findDeformer(this.deformerId);\n if (this.prevHadParent) {\n deformer.parent = this.prevParent;\n } else {\n delete deformer.parent;\n }\n }\n}\n\n/**\n * Add a new part to the model. Validates the candidate model with\n * {@link parseIkiModel} BEFORE mutating, so a structurally invalid part\n * (bad color tuple, missing required fields, id collision with a deformer)\n * throws an `IkiFormatError` and leaves the model untouched.\n *\n * Captures the prior base-UV entry for the part's id on the FIRST apply so\n * invert can restore the exact pre-add state. This guards the id-reuse hazard:\n * DeletePart(X) → AddPart(X′, different mesh) → undo(add) → undo(delete) —\n * without restore, X's constructor-captured base would be gone, causing\n * applyAtlas to fail when X is restored by the undo of the delete.\n */\nexport class AddPart implements EditCommand {\n readonly label = \"Add part\";\n private readonly part: IkiPart;\n private captured = false;\n private prevBaseMeshUvs: number[] | undefined = undefined;\n\n constructor(part: IkiPart) {\n // Clone on construction — prevents caller mutation from corrupting apply/redo.\n this.part = structuredClone(part);\n }\n\n apply(doc: EditorDocument): void {\n // (a) Cheap id-uniqueness pre-check with a source-qualified message.\n const hit = findIdCollision(doc.getModel(), this.part.id);\n if (hit === \"part\") {\n throw new Error(\n `parts: id \"${this.part.id}\" collides with an existing part id`,\n );\n }\n if (hit === \"deformer\") {\n throw new Error(\n `parts: id \"${this.part.id}\" collides with an existing deformer id`,\n );\n }\n\n // (b) Full structural validation on a candidate clone — propagate\n // IkiFormatError unchanged so the caller gets a path-qualified message.\n const candidate = structuredClone(doc.getModel());\n candidate.parts.push(structuredClone(this.part));\n parseIkiModel(candidate);\n\n // (c) All checks pass — mutate the real model with a fresh clone so the\n // model never aliases the command's stored part.\n doc.getModel().parts.push(structuredClone(this.part));\n\n // Register base mesh UVs so applyAtlas can remap this part. Capture the\n // prior entry on the FIRST apply only — redo must NOT re-capture or it\n // would clobber the saved prior and make invert unable to restore correctly.\n const prev = doc.captureBaseMeshUvs(this.part.id);\n if (!this.captured) {\n this.prevBaseMeshUvs = prev;\n this.captured = true;\n }\n }\n\n invert(doc: EditorDocument): void {\n const parts = doc.getModel().parts;\n const i = parts.findIndex((p) => p.id === this.part.id);\n if (i !== -1) parts.splice(i, 1);\n // Restore the exact prior base-UV state so a constructor-captured entry for\n // a deleted part with this id survives the undo of the add.\n doc.restoreBaseMeshUvs(this.part.id, this.prevBaseMeshUvs);\n }\n}\n\n/**\n * Add a new deformer (matrix or warp) to the model. Validates the candidate\n * model with {@link parseIkiModel} BEFORE mutating — this enforces the warp\n * rest-grid invariant, points length, pivot, parent, and bindings without\n * hand-rolling partial checks. Mirrors {@link AddPart} but also tracks whether\n * `model.deformers` was absent before the first apply, so `invert` can restore\n * the exact key-absence state (mirrors {@link SetDeformerBindings}).\n */\nexport class AddDeformer implements EditCommand {\n readonly label = \"Add deformer\";\n private readonly deformer: IkiDeformer;\n private captured = false;\n private prevDeformersAbsent = false;\n\n constructor(deformer: IkiDeformer) {\n // Clone on construction — prevents caller mutation from corrupting apply/redo.\n this.deformer = structuredClone(deformer);\n }\n\n apply(doc: EditorDocument): void {\n const model = doc.getModel();\n\n // (a) Cheap id-uniqueness pre-check with a source-qualified message.\n const hit = findIdCollision(model, this.deformer.id);\n if (hit === \"deformer\") {\n throw new Error(\n `deformers: id \"${this.deformer.id}\" collides with an existing deformer id`,\n );\n }\n if (hit === \"part\") {\n throw new Error(\n `deformers: id \"${this.deformer.id}\" collides with an existing part id`,\n );\n }\n\n // (b) Full structural validation on a candidate clone.\n const candidate = structuredClone(model);\n candidate.deformers = [\n ...(candidate.deformers ?? []),\n structuredClone(this.deformer),\n ];\n parseIkiModel(candidate);\n\n // (c) All checks pass — capture-once, then mutate.\n if (!this.captured) {\n this.prevDeformersAbsent = model.deformers === undefined;\n this.captured = true;\n }\n if (model.deformers === undefined) {\n model.deformers = [];\n }\n model.deformers.push(structuredClone(this.deformer));\n }\n\n invert(doc: EditorDocument): void {\n const model = doc.getModel();\n const arr = model.deformers;\n if (!arr) return;\n const i = arr.findIndex((d) => d.id === this.deformer.id);\n if (i !== -1) arr.splice(i, 1);\n // Restore the absent-vs-present distinction. If deformers did not exist\n // before apply, delete the key once the array is empty again.\n if (this.prevDeformersAbsent && arr.length === 0) {\n delete model.deformers;\n }\n }\n}\n\n/**\n * Delete a part by id, preserving its original array slot so `invert` restores\n * it at the same position. Slot position is cosmetic (the renderer uses the\n * `order` field for paint ordering), but restoring the index keeps undo\n * visually predictable.\n *\n * No `parseIkiModel` pre-check is needed: removing an element from an already-\n * valid model cannot introduce a structural violation — EXCEPT for clip-mask\n * references, the one part→part reference in the contract. `apply` refuses to\n * delete a part still used as another part's `clip.masks` entry (guard below),\n * so it can never leave a dangling mask ref that would fail `toIkiModel()`.\n *\n * Texture-reference safety (package invariant): `apply` refuses to delete a\n * part that still carries `part.texture`. Texture/atlas state is non-undoable\n * per the 5b boundary; clear the texture first via\n * {@link EditorDocument.clearPartTextureRef} (model-committed) or\n * {@link EditorDocument.applyAtlas} with no assignment (imported) — both are\n * non-undoable. By the time a part is deletable it carries no texture, so\n * `invert` can never restore a stale texture index that would render the wrong\n * atlas region after a later atlas repack. No transactional atlas capture is\n * needed in this command.\n */\nexport class DeletePart implements EditCommand {\n readonly label = \"Delete part\";\n private captured = false;\n private removed!: IkiPart;\n private index!: number;\n\n constructor(private readonly partId: string) {}\n\n apply(doc: EditorDocument): void {\n // Validate FIRST — throws with path-qualified message if unknown.\n const part = doc.findPart(this.partId);\n\n // Texture guard — enforced at the `@ikijs/editor` boundary so public callers\n // cannot bypass it (the example store adds a friendly pre-check, but this\n // is the real invariant). Throw before any capture or mutation.\n if (part.texture !== undefined) {\n throw new Error(\n `parts.\"${this.partId}\": cannot delete — part has a texture reference; clear its texture first`,\n );\n }\n\n const parts = doc.getModel().parts;\n\n // Clip-mask guard — `clip.masks` is the one part→part reference in the model\n // contract. Deleting a referenced mask would leave a dangling ref that fails\n // parseIkiModel on toIkiModel(). Refuse rather than corrupt (mirrors the\n // texture guard above). Throw before any capture or mutation.\n const masker = parts.find(\n (p) => p.id !== this.partId && p.clip?.masks.includes(this.partId),\n );\n if (masker) {\n throw new Error(\n `parts.\"${this.partId}\": cannot delete — used as a clip mask by part \"${masker.id}\"; remove its clip first`,\n );\n }\n\n const i = parts.indexOf(part);\n if (!this.captured) {\n this.removed = structuredClone(part);\n this.index = i;\n this.captured = true;\n }\n parts.splice(i, 1);\n }\n\n invert(doc: EditorDocument): void {\n // Restore at the original slot — exact deep restore including bindings and\n // mesh. No texture key is present (apply enforced that invariant before\n // capture), so the snapshot is always atlas-safe on restore.\n doc.getModel().parts.splice(this.index, 0, structuredClone(this.removed));\n }\n}\n\n/**\n * Delete a deformer by id. Calls {@link validateDeformerDelete} FIRST so the\n * delete is refused while anything still references it — a child deformer, an\n * attached part, or a physics chain anchored to it — enforcing the same\n * referential safety as {@link SetDeformerParent} and {@link SetPartDeformer}.\n *\n * `invert` re-inserts the deformer at its original index.\n */\nexport class DeleteDeformer implements EditCommand {\n readonly label = \"Delete deformer\";\n private captured = false;\n private removed!: IkiDeformer;\n private index!: number;\n\n constructor(private readonly deformerId: string) {}\n\n apply(doc: EditorDocument): void {\n const model = doc.getModel();\n // Validate FIRST — throws before capture/mutate on any referential violation.\n validateDeformerDelete(\n model.deformers ?? [],\n model.parts,\n model.physicsChains ?? [],\n this.deformerId,\n );\n // validateDeformerDelete guarantees the deformer (and thus the array) exists.\n const arr = model.deformers!;\n const i = arr.findIndex((d) => d.id === this.deformerId);\n if (!this.captured) {\n this.removed = structuredClone(arr[i]);\n this.index = i;\n this.captured = true;\n }\n arr.splice(i, 1);\n }\n\n invert(doc: EditorDocument): void {\n // Re-insert at the original slot. `apply` only captures after\n // validateDeformerDelete passed, so the array it spliced out of is present:\n // fabricating one here would hide a broken undo stack and silently restore\n // just this node instead of surfacing the loss of the rest of the hierarchy.\n doc\n .getModel()\n .deformers!.splice(this.index, 0, structuredClone(this.removed));\n }\n}\n\n/**\n * Replace a part's `bindings` array wholesale. A single command covers add,\n * edit, and remove (pass the desired final array; pass `[]` to remove all).\n * Mirrors {@link SetDeformerBindings}'s deep-copy and absent-vs-empty discipline:\n * clone-on-construction, capture-once, fresh deep copy on every assign/invert.\n *\n * Each {@link IkiBinding} is a flat object, so a per-element spread `{ ...b }`\n * is a sufficient deep copy.\n *\n * Validates the WRITTEN bindings against the declared parameters via a narrow\n * synthetic {@link parseIkiModel} candidate (so unrelated in-flight invalid\n * editor state — e.g. a NaN width on another part — cannot false-reject a\n * binding edit). Validation runs BEFORE any mutation; on failure the model and\n * undo stack are left untouched.\n *\n * Empty bindings → omit the `bindings` key on the candidate AND delete\n * `part.bindings` on apply (keeps the model shape minimal; represents \"no\n * bindings\" as an absent key rather than an empty array).\n */\nexport class SetPartBindings implements EditCommand {\n readonly label = \"Set part bindings\";\n private readonly bindings: IkiBinding[];\n private captured = false;\n private prevBindings!: IkiBinding[] | undefined;\n\n constructor(\n private readonly partId: string,\n bindings: IkiBinding[],\n ) {\n // Clone the caller's array on construction — prevents post-execute mutation\n // of the caller's array from corrupting apply/redo.\n this.bindings = bindings.map((b) => ({ ...b }));\n }\n\n apply(doc: EditorDocument): void {\n // Build a narrow synthetic candidate carrying only the validation-relevant\n // context. A full structuredClone(doc.getModel()) is deliberately avoided\n // because unrelated parts may carry NaN in-flight values (e.g. from\n // NumberField.valueAsNumber), which would cause false-positive validation\n // failures. The synthetic model is the minimal shape parseIkiModel accepts.\n const candidatePart: Record<string, unknown> = {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n };\n // Omit the bindings key entirely when empty — \"no bindings\" is represented\n // as key absence; an empty array is not a valid value in the format contract.\n if (this.bindings.length > 0) {\n candidatePart.bindings = this.bindings.map((b) => ({ ...b }));\n }\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [candidatePart],\n };\n // Validation before any mutation. The synthetic candidate always places the\n // part at parts[0], so the validator emits paths like \"parts[0].bindings[i]\".\n // Rewrite that prefix to name the real target so the surfaced error is\n // actionable (\"parts.\"part-a\".bindings[i]\" rather than \"parts[0].bindings[i]\").\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n throw new IkiFormatError(\n e.message.replace(/^parts\\[0\\]/, `parts.\"${this.partId}\"`),\n );\n }\n throw e;\n }\n\n // Resolution after validation so an unknown partId throws with a\n // path-qualified message (findPart throws) but only after the bindings\n // themselves are confirmed structurally valid.\n const part = doc.findPart(this.partId);\n if (!this.captured) {\n // Preserve the original absent-vs-empty distinction.\n this.prevBindings =\n part.bindings === undefined\n ? undefined\n : part.bindings.map((b) => ({ ...b }));\n this.captured = true;\n }\n if (this.bindings.length > 0) {\n // Assign a fresh deep copy — model must never alias the command's stored array.\n part.bindings = this.bindings.map((b) => ({ ...b }));\n } else {\n // Delete the key on empty: keeps the model shape minimal and correctly\n // represents \"no bindings\" as an absent key rather than an empty array.\n delete part.bindings;\n }\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n if (this.prevBindings === undefined) {\n delete part.bindings;\n } else {\n // Assign a fresh deep copy — never alias the captured array so re-apply\n // after undo cannot corrupt the saved prior value.\n part.bindings = this.prevBindings.map((b) => ({ ...b }));\n }\n }\n}\n\n/**\n * Attach a part to a deformer, or detach it (`newDeformerId === undefined`).\n * Calls {@link validatePartAttach} FIRST so invalid attachments (warp without\n * mesh, unknown ids) throw before any capture or mutation.\n *\n * Absent-vs-present distinction mirrors {@link SetDeformerParent}: captures\n * both the prior `deformer` value and whether the key was present, so `invert`\n * can delete the key rather than assigning `undefined`.\n */\nexport class SetPartDeformer implements EditCommand {\n readonly label = \"Set part deformer\";\n private captured = false;\n private prevDeformer: string | undefined = undefined;\n private prevHadDeformer = false;\n\n constructor(\n private readonly partId: string,\n private readonly newDeformerId: string | undefined,\n ) {}\n\n apply(doc: EditorDocument): void {\n // Validate FIRST — throws before capture/mutate on any violation.\n validatePartAttach(\n doc.getModel().deformers ?? [],\n this.partId,\n doc.getModel().parts,\n this.newDeformerId,\n );\n const part = doc.findPart(this.partId);\n if (!this.captured) {\n this.prevHadDeformer = Object.prototype.hasOwnProperty.call(\n part,\n \"deformer\",\n );\n this.prevDeformer = part.deformer;\n this.captured = true;\n }\n if (this.newDeformerId !== undefined) {\n part.deformer = this.newDeformerId;\n } else {\n delete part.deformer;\n }\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n if (this.prevHadDeformer) {\n part.deformer = this.prevDeformer;\n } else {\n delete part.deformer;\n }\n }\n}\n\n/**\n * Return true if the deformer identified by `deformerId` exists in the model\n * and has `kind === \"warp\"`. Used by SetPartMesh to detect warp-deformer\n * attachment without importing reparent.ts internals.\n */\nfunction isWarpDeformer(model: IkiModel, deformerId: string): boolean {\n const d = (model.deformers ?? []).find((x) => x.id === deformerId);\n return d?.kind === \"warp\";\n}\n\n/**\n * Add, regenerate, or remove the triangle mesh on a part.\n *\n * - `mesh !== undefined` → add or replace the mesh, registering the\n * unit-square base UVs in the side-table so {@link EditorDocument.applyAtlas}\n * can remap them later.\n * - `mesh === undefined` → delete `part.mesh` and remove the side-table entry.\n *\n * Fails fast (BEFORE any mutation) on warp-topology violations:\n * - REMOVE while `part.warps` is present (even empty) or the part is\n * attached to a warp deformer — the format rejects any `warps` key once\n * the mesh is gone.\n * - ADD/REPLACE while `part.warps` has authored offsets (`length > 0`) —\n * regenerating the mesh invalidates offset positions silently; the user\n * must remove the warps first.\n *\n * The remove guard checks PRESENCE of `part.warps` (not length) while the\n * add/replace guard checks LENGTH > 0. This asymmetry is intentional: the\n * format allows `warps: []` only when a mesh exists, so any present key\n * (even empty) would become invalid after mesh removal; but replacing a mesh\n * under an empty `warps: []` is harmless because there are no authored offsets.\n */\nexport class SetPartMesh implements EditCommand {\n readonly label = \"Set part mesh\";\n private readonly mesh: IkiMesh | undefined;\n private captured = false;\n private prevHadMesh = false;\n private prevMesh: IkiMesh | undefined;\n private prevBaseMeshUvs: number[] | undefined;\n\n constructor(\n private readonly partId: string,\n mesh: IkiMesh | undefined,\n ) {\n // Clone on construction — prevents caller mutation from corrupting apply/redo.\n this.mesh = mesh === undefined ? undefined : structuredClone(mesh);\n }\n\n apply(doc: EditorDocument): void {\n // (a) Resolve the live part up front — unlike SetPartBindings, which resolves\n // after parseIkiModel, we need the live part here because the warp-topology\n // guards at step (c) inspect part.warps / part.deformer before any mutation.\n const part = doc.findPart(this.partId);\n\n // (b) Structural validation — only needed when adding or replacing a mesh.\n // Build a NARROW synthetic candidate carrying only the new mesh so that\n // unrelated in-flight parts with NaN values cannot cause false failures.\n if (this.mesh !== undefined) {\n const candidatePart = {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n mesh: structuredClone(this.mesh),\n };\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [candidatePart],\n };\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n throw new IkiFormatError(\n e.message.replace(/^parts\\[0\\]/, `parts.\"${this.partId}\"`),\n );\n }\n throw e;\n }\n }\n\n // (c) Warp-topology fail-fast — BEFORE any mutation, after structural validation.\n // The two paths key on DIFFERENT predicates; this asymmetry is intentional\n // (see class JSDoc above).\n const attachedToWarp =\n part.deformer !== undefined &&\n isWarpDeformer(doc.getModel(), part.deformer);\n\n if (this.mesh === undefined) {\n // REMOVE: guard on warps PRESENCE (even empty) OR warp-deformer attachment.\n // The format rejects ANY present `warps` key once the mesh is gone, so even\n // an empty array would make toIkiModel() throw.\n if (part.warps !== undefined || attachedToWarp) {\n throw new IkiFormatError(\n `parts.\"${this.partId}\": cannot remove mesh — part has warps or is attached to a warp deformer; remove its warps / detach from the warp deformer first`,\n );\n }\n // Clip-mask guard — the format requires a clip mask to be a mesh part, so\n // stripping the mesh from a referenced mask would dangle the ref and fail\n // toIkiModel(). Mirrors the DeletePart clip-mask guard.\n const masker = doc\n .getModel()\n .parts.find(\n (p) => p.id !== this.partId && p.clip?.masks.includes(this.partId),\n );\n if (masker) {\n throw new IkiFormatError(\n `parts.\"${this.partId}\": cannot remove mesh — used as a clip mask by part \"${masker.id}\" (masks require a mesh); remove its clip first`,\n );\n }\n } else {\n // ADD/REPLACE: guard on authored offsets (length > 0). An empty warps: []\n // has no offsets to invalidate, so replacing the mesh under it is harmless.\n if ((part.warps?.length ?? 0) > 0) {\n throw new IkiFormatError(\n `parts.\"${this.partId}\": cannot regenerate mesh — part has warps whose offsets are bound to the current rest mesh; remove its warps first`,\n );\n }\n }\n\n // (d) Mutate + side-table maintenance.\n\n // (i) Single first-apply capture block — captures BOTH prevMesh and\n // prevBaseMeshUvs together, BEFORE any mutation. captureBaseMeshUvs has\n // a side effect (registers current mesh.uvs); step (iii) overwrites it.\n if (!this.captured) {\n this.prevHadMesh = part.mesh !== undefined;\n this.prevMesh = part.mesh ? structuredClone(part.mesh) : undefined;\n this.prevBaseMeshUvs = doc.captureBaseMeshUvs(this.partId);\n this.captured = true;\n }\n // Redo: do NOT re-capture (would clobber the saved prior). The mutation\n // below is fully reconstructable from this.mesh + this.partId.\n\n // (ii) Apply the model mutation.\n if (this.mesh !== undefined) {\n // Compute stored UVs: if the part has an active texture, remap the\n // unit-square base UVs into the texture's atlas sub-rectangle.\n const storedUvs =\n part.texture !== undefined\n ? remapMeshUvsToRect(this.mesh.uvs, part.texture.uv)\n : this.mesh.uvs.slice();\n part.mesh = {\n vertices: this.mesh.vertices.slice(),\n uvs: storedUvs,\n indices: this.mesh.indices.slice(),\n };\n } else {\n delete part.mesh;\n }\n\n // (iii) Re-register the side-table to the correct final state, overwriting\n // the (i) read's incidental re-registration. Write ONLY via\n // restoreBaseMeshUvs — never via a new setBaseMeshUvs API.\n if (this.mesh !== undefined) {\n // Register the UNIT-SQUARE base (not the texture-remapped storedUvs) so\n // applyAtlas can always derive correct atlas-space UVs from the base.\n doc.restoreBaseMeshUvs(this.partId, this.mesh.uvs.slice());\n } else {\n doc.restoreBaseMeshUvs(this.partId, undefined);\n }\n }\n\n invert(doc: EditorDocument): void {\n const part = doc.findPart(this.partId);\n // Restore the mesh, preserving the absent-vs-present distinction.\n // applyAtlas (and texture changes generally) are NON-undoable and do NOT\n // clear the undo stack. So by the time undo() is called, part.texture may\n // have been changed by a later applyAtlas that this command never saw. To\n // avoid restoring stale texture-space UVs, rebuild uvs from the captured\n // unit-square base against the CURRENT texture rect rather than trusting\n // prevMesh.uvs verbatim.\n if (this.prevHadMesh) {\n // A mesh part ALWAYS has a registered unit-square base under the invariant\n // (applyAtlas preflights requireBaseUvs for every mesh part). If the base is\n // absent here the side-table invariant is broken — fail fast rather than\n // silently restoring stale texture-space uvs that would corrupt rendering.\n if (this.prevBaseMeshUvs === undefined) {\n throw new Error(\n `parts.\"${this.partId}\": cannot invert SetPartMesh — no base mesh uvs captured for a mesh part (broken side-table invariant)`,\n );\n }\n const restored = structuredClone(this.prevMesh!);\n // Remap the unit-square base into the current texture rect (if any).\n restored.uvs =\n part.texture !== undefined\n ? remapMeshUvsToRect(this.prevBaseMeshUvs, part.texture.uv)\n : this.prevBaseMeshUvs.slice();\n part.mesh = restored;\n } else {\n delete part.mesh;\n }\n // Restore the side-table to the exact prior state (unit-square base).\n doc.restoreBaseMeshUvs(this.partId, this.prevBaseMeshUvs);\n }\n}\n\n/**\n * Validate a candidate `physics` array against the model's declared parameters\n * via a NARROW synthetic model — full `parameters` + the full candidate physics\n * array + one trivial part. Mirrors {@link SetPartBindings}' synthetic-candidate\n * (avoids false-positives from unrelated in-flight NaN part numerics) but carries\n * the FULL physics array so the cross-rig rules (dup id / dup output / feedback)\n * run. On `IkiFormatError`, rewrite the failing `physics[n]` path to name the rig\n * AT THE FAILING INDEX — a cross-rig failure can surface at a different index than\n * the edited rig, so the rewrite follows the message index, not the command target.\n */\nfunction validatePhysicsCandidate(\n doc: EditorDocument,\n candidatePhysics: IkiPhysics[],\n): void {\n const candidatePart: Record<string, unknown> = {\n id: \"_\",\n color: [0, 0, 0, 1],\n width: 1,\n height: 1,\n transform: { x: 0, y: 0 },\n order: 0,\n };\n const candidate = {\n version: IKI_FORMAT_VERSION,\n name: \"_\",\n canvas: { width: 1, height: 1 },\n parameters: doc.getModel().parameters,\n parts: [candidatePart],\n deformers: doc.getModel().deformers,\n physics: candidatePhysics,\n physicsChains: doc.getModel().physicsChains,\n };\n try {\n parseIkiModel(candidate);\n } catch (e) {\n if (e instanceof IkiFormatError) {\n const m = e.message.match(/^physics\\[(\\d+)\\]/);\n const rigId = m ? candidatePhysics[Number(m[1])]?.id : undefined;\n if (rigId !== undefined) {\n throw new IkiFormatError(\n e.message.replace(/^physics\\[\\d+\\]/, `physics.\"${rigId}\"`),\n );\n }\n }\n throw e;\n }\n}\n\n/**\n * Add a physics rig to `model.physics`. Mirrors {@link AddDeformer}: clone on\n * construction, cheap friendly duplicate-id pre-check, full synthetic-candidate\n * validation before mutating, capture the absent-vs-present `physics` state once,\n * and on invert delete the key when the array empties back to its prior absence.\n */\nexport class AddPhysicsRig implements EditCommand {\n readonly label = \"Add physics rig\";\n private readonly rig: IkiPhysics;\n private captured = false;\n private prevPhysicsAbsent = false;\n\n constructor(rig: IkiPhysics) {\n // Deep clone — input/output are nested objects a shallow spread would alias.\n this.rig = structuredClone(rig);\n }\n\n apply(doc: EditorDocument): void {\n const model = doc.getModel();\n // (a) Friendly duplicate-id pre-check (the format check from validate.ts is\n // the real guard; this surfaces an actionable message before validate).\n if ((model.physics ?? []).some((r) => r.id === this.rig.id)) {\n throw new Error(\n `physics: id \"${this.rig.id}\" collides with an existing physics rig id`,\n );\n }\n // (b) Full-physics synthetic validation with the rig appended.\n validatePhysicsCandidate(doc, [\n ...(model.physics ?? []),\n structuredClone(this.rig),\n ]);\n // (c) Capture-once, then mutate with a fresh clone.\n if (!this.captured) {\n this.prevPhysicsAbsent = model.physics === undefined;\n this.captured = true;\n }\n if (model.physics === undefined) {\n model.physics = [];\n }\n model.physics.push(structuredClone(this.rig));\n }\n\n invert(doc: EditorDocument): void {\n const model = doc.getModel();\n const arr = model.physics;\n if (!arr) return;\n const i = arr.findIndex((r) => r.id === this.rig.id);\n if (i !== -1) arr.splice(i, 1);\n if (this.prevPhysicsAbsent && arr.length === 0) {\n delete model.physics;\n }\n }\n}\n\n/**\n * Delete a physics rig by id. Mirrors {@link DeleteDeformer}: resolve/validate\n * first, capture the removed rig + its index once, splice. Removing the LAST rig\n * deletes the `physics` key to keep the exported shape minimal; invert re-inserts\n * at the original index (recreating the array if it was deleted).\n */\nexport class DeletePhysicsRig implements EditCommand {\n readonly label = \"Delete physics rig\";\n private captured = false;\n private removed!: IkiPhysics;\n private index!: number;\n\n constructor(private readonly rigId: string) {}\n\n apply(doc: EditorDocument): void {\n const rig = doc.findPhysicsRig(this.rigId); // throws if unknown\n const arr = doc.getModel().physics!;\n const i = arr.indexOf(rig);\n if (!this.captured) {\n this.removed = structuredClone(rig);\n this.index = i;\n this.captured = true;\n }\n arr.splice(i, 1);\n // Minimal exported shape: drop the key once the last rig is gone.\n if (arr.length === 0) {\n delete doc.getModel().physics;\n }\n }\n\n invert(doc: EditorDocument): void {\n const model = doc.getModel();\n (model.physics ??= []).splice(this.index, 0, structuredClone(this.removed));\n }\n}\n\n/**\n * Replace a physics rig in place (tuning). Mirrors {@link SetDeformerBindings}\n * but DEEP-clones the nested `input`/`output` (a shallow spread would alias them).\n * Forbids rename (`rig.id` must equal the target `rigId`) — this command tunes a\n * rig, never re-keys it. Validates the whole candidate (the edited rig swapped in\n * at its index) so cross-rig rules still run, then captures the prior rig once.\n */\nexport class SetPhysicsRig implements EditCommand {\n readonly label = \"Set physics rig\";\n private readonly rig: IkiPhysics;\n private captured = false;\n private prevRig!: IkiPhysics;\n\n constructor(\n private readonly rigId: string,\n rig: IkiPhysics,\n ) {\n this.rig = structuredClone(rig);\n }\n\n apply(doc: EditorDocument): void {\n // No-rename guard — fail before mutating.\n if (this.rig.id !== this.rigId) {\n throw new Error(\n `physics.\"${this.rigId}\": cannot change rig id to \"${this.rig.id}\" (rename unsupported)`,\n );\n }\n const model = doc.getModel();\n const i = (model.physics ?? []).findIndex((r) => r.id === this.rigId);\n if (i === -1) {\n throw new Error(`physics: no physics rig with id \"${this.rigId}\"`);\n }\n // Validate a candidate with the edited rig swapped in at its index.\n const candidate = model.physics!.map((r, idx) =>\n idx === i ? structuredClone(this.rig) : r,\n );\n validatePhysicsCandidate(doc, candidate);\n if (!this.captured) {\n this.prevRig = structuredClone(model.physics![i]);\n this.captured = true;\n }\n model.physics![i] = structuredClone(this.rig);\n }\n\n invert(doc: EditorDocument): void {\n const arr = doc.getModel().physics;\n if (!arr) return;\n const i = arr.findIndex((r) => r.id === this.rigId);\n if (i !== -1) arr[i] = structuredClone(this.prevRig);\n }\n}\n","import type { IkiGridKeyform } from \"@ikijs/format\";\n\n/**\n * Pure, grid-size-agnostic keyform/offset math for authoring a warp-deformer\n * grid by dragging. No DOM, no `@ikijs/engine` — the load-bearing testable core.\n * Constraints derive only from the input array lengths, never the sample grid.\n */\n\n/**\n * Interpolate the grid offsets at `value`, mirroring the engine's\n * `accumulateKeyformOffsets` clamp+lerp semantics: clamp to the first/last\n * keyform (NO extrapolation) and linearly interpolate the bracketing pair.\n * Returns a NEW array of length `keyforms[0].offsets.length`. Throws on empty.\n */\nexport function interpolateGridOffsets(\n keyforms: { value: number; offsets: number[] }[],\n value: number,\n): number[] {\n if (keyforms.length === 0) {\n throw new Error(\"interpolateGridOffsets: keyforms must be non-empty\");\n }\n\n if (value <= keyforms[0].value) {\n return [...keyforms[0].offsets];\n }\n const last = keyforms[keyforms.length - 1];\n if (value >= last.value) {\n return [...last.offsets];\n }\n\n // Find the bracketing pair (keyforms are small in practice).\n let lo = keyforms[0];\n let hi = keyforms[1];\n for (let k = 1; k < keyforms.length - 1; k++) {\n if (keyforms[k].value <= value) {\n lo = keyforms[k];\n hi = keyforms[k + 1];\n }\n }\n const t = (value - lo.value) / (hi.value - lo.value);\n return lo.offsets.map((loOff, i) => loOff + (hi.offsets[i] - loOff) * t);\n}\n\n/**\n * Per-control-point delta of the dragged grid from the rest grid: for each\n * point `i`, `(draggedX_i - restX_i, draggedY_i - restY_i)`. The DOM layer\n * assembles the full `restFrameDraggedPoints` (including untouched points), so\n * this is a straight subtract — no prior-offset blending.\n *\n * Both arrays must have the SAME length and that length must be even (x,y\n * pairs). Returns a NEW array of length `restPoints.length`.\n */\nexport function computeGridOffsets(\n restPoints: number[],\n restFrameDraggedPoints: number[],\n): number[] {\n if (restPoints.length !== restFrameDraggedPoints.length) {\n throw new Error(\n `computeGridOffsets: restFrameDraggedPoints length ${restFrameDraggedPoints.length} must equal restPoints length ${restPoints.length}`,\n );\n }\n if (restPoints.length % 2 !== 0) {\n throw new Error(\n `computeGridOffsets: restPoints length ${restPoints.length} must be even (x,y pairs)`,\n );\n }\n return restPoints.map((rest, i) => restFrameDraggedPoints[i] - rest);\n}\n\n/**\n * Insert or replace the keyform at `value`, returning a NEW array. If a keyform\n * already exists with an exact-match `value`, REPLACE its offsets (with a copy);\n * otherwise INSERT `{ value, offsets: [...offsets] }` at the position that keeps\n * the array strictly ascending by value. The input array and its keyform objects\n * are never mutated, and `offsets` is copied so the result never aliases the\n * caller's array.\n *\n * Deliberately RANGE-FREE — a generic, reusable array op. Value-range\n * enforcement is the command's job, not this helper's.\n */\nexport function upsertGridKeyform(\n keyforms: IkiGridKeyform[],\n value: number,\n offsets: number[],\n): IkiGridKeyform[] {\n const result = keyforms.map((kf) => ({\n value: kf.value,\n offsets: [...kf.offsets],\n }));\n const existing = result.findIndex((kf) => kf.value === value);\n if (existing !== -1) {\n result[existing] = { value, offsets: [...offsets] };\n return result;\n }\n const insertAt = result.findIndex((kf) => kf.value > value);\n const entry: IkiGridKeyform = { value, offsets: [...offsets] };\n if (insertAt === -1) {\n result.push(entry);\n } else {\n result.splice(insertAt, 0, entry);\n }\n return result;\n}\n","import type { IkiDeformer, IkiPart, IkiPhysicsChain } from \"@ikijs/format\";\n\n/**\n * Pure, DOM-free validation helpers for deformer reparenting and part attachment.\n * Each function throws a path-qualified plain Error on rejection and returns void\n * on success. Neither function mutates the input arrays or objects.\n */\n\nfunction kindOf(d: IkiDeformer): \"warp\" | \"matrix\" {\n return d.kind === \"warp\" ? \"warp\" : \"matrix\";\n}\n\n/**\n * Validate that reparenting `deformerId` under `newParentId` keeps the deformer\n * hierarchy valid. Pass `newParentId === undefined` to move to root (always legal).\n * Checks: existence, self-reference, undeclared parent, kind constraint (a warp\n * deformer cannot be the parent of another warp deformer), a matrix deformer's\n * pivot inside its new warp parent's rest grid, and cycle detection via the\n * proposed edge.\n */\nexport function validateDeformerReparent(\n deformers: IkiDeformer[],\n deformerId: string,\n newParentId: string | undefined,\n): void {\n // (1) Target deformer must exist.\n const target = deformers.find((d) => d.id === deformerId);\n if (target === undefined) {\n throw new Error(`deformers: no deformer with id \"${deformerId}\"`);\n }\n\n // (2) Root is always legal.\n if (newParentId === undefined) return;\n\n // (3) Self-reference.\n if (newParentId === deformerId) {\n throw new Error(\n `deformers.\"${deformerId}\".parent \"${newParentId}\" is a self-reference`,\n );\n }\n\n // (4) Parent must be declared.\n const parent = deformers.find((d) => d.id === newParentId);\n if (parent === undefined) {\n throw new Error(\n `deformers.\"${deformerId}\".parent \"${newParentId}\" is not a declared deformer`,\n );\n }\n\n // (5) A warp deformer cannot be nested under another warp deformer.\n if (kindOf(parent) === \"warp\" && kindOf(target) === \"warp\") {\n throw new Error(\n `deformers.\"${deformerId}\".parent \"${newParentId}\" must be a matrix deformer (warp deformers cannot be nested under a warp deformer)`,\n );\n }\n\n // (6) A matrix deformer's pivot must lie inside its warp parent's rest grid,\n // as the format requires. Refusing here keeps the bad edge out of the\n // model and the undo stack; a pivot moved out later (typed digit by\n // digit through invalid values) is still left to the export check.\n if (parent.kind === \"warp\" && target.kind !== \"warp\") {\n const { pivot } = target;\n // The same corners the format validator reads (row 0 is the top, column 0\n // the left), so a grid with in-tolerance jitter cannot pass here and then\n // fail at export.\n const { cols, rows, points } = parent.grid;\n const xMin = points[0];\n const xMax = points[2 * cols];\n const yMax = points[1];\n const yMin = points[rows * (cols + 1) * 2 + 1];\n if (pivot.x < xMin || pivot.x > xMax || pivot.y < yMin || pivot.y > yMax) {\n throw new Error(\n `deformers.\"${deformerId}\".pivot (${pivot.x}, ${pivot.y}) lies outside its warp parent \"${newParentId}\" rest grid x ${xMin}..${xMax}, y ${yMin}..${yMax}`,\n );\n }\n }\n\n // (7) Cycle detection: build parentOf from current state, then override with\n // the proposed edge, and walk from deformerId following the chain.\n const parentOf = new Map<string, string>();\n for (const d of deformers) {\n if (d.parent !== undefined) parentOf.set(d.id, d.parent);\n }\n // Override with the proposed edge.\n parentOf.set(deformerId, newParentId);\n\n const visited = new Set<string>();\n let cur: string | undefined = deformerId;\n while (cur !== undefined) {\n if (visited.has(cur)) {\n throw new Error(\n `deformers: reparenting \"${deformerId}\" under \"${newParentId}\" would create a cycle`,\n );\n }\n visited.add(cur);\n cur = parentOf.get(cur);\n }\n}\n\n/**\n * Validate that deleting `deformerId` is safe. Throws when the deformer does\n * not exist, when another deformer is parented to it (must be reparented or\n * detached first), when a part is attached to it (must be detached first), or\n * when a physics chain anchors to it (must be re-anchored or deleted first).\n *\n * Every id that can reference a deformer must be covered here: the format\n * validator rejects a dangling reference at export, so a delete this function\n * lets through does not fail now — it strands the document in a state\n * `toIkiModel()` refuses.\n *\n * Note: there is no validatePartDelete here, but NOT because parts are\n * unreferenced — `clip.masks` names parts by id. That invariant is enforced\n * closer to the edits that could break it: `DeletePart` refuses to remove a\n * part still used as a mask, and `SetPartMesh` refuses to strip the mesh off\n * one (masks must be mesh parts). No command creates or edits `clip`.\n */\nexport function validateDeformerDelete(\n deformers: IkiDeformer[],\n parts: IkiPart[],\n physicsChains: IkiPhysicsChain[],\n deformerId: string,\n): void {\n // (1) Target deformer must exist.\n const target = deformers.find((d) => d.id === deformerId);\n if (target === undefined) {\n throw new Error(`deformers: no deformer with id \"${deformerId}\"`);\n }\n\n // (2) No other deformer may be parented to it.\n const childDeformer = deformers.find((d) => d.parent === deformerId);\n if (childDeformer !== undefined) {\n throw new Error(\n `deformers.\"${deformerId}\": cannot delete — deformer \"${childDeformer.id}\" is parented to it; reparent or detach it first`,\n );\n }\n\n // (3) No part may be attached to it.\n const attachedPart = parts.find((p) => p.deformer === deformerId);\n if (attachedPart !== undefined) {\n throw new Error(\n `deformers.\"${deformerId}\": cannot delete — part \"${attachedPart.id}\" is attached to it; detach it first`,\n );\n }\n\n // (4) No physics chain may anchor to it.\n const anchoredChain = physicsChains.find(\n (c) => c.anchorDeformer === deformerId,\n );\n if (anchoredChain !== undefined) {\n throw new Error(\n `deformers.\"${deformerId}\": cannot delete — physics chain \"${anchoredChain.id}\" anchors to it; re-anchor or delete the chain first`,\n );\n }\n}\n\n/**\n * Validate that attaching part `partId` to deformer `newDeformerId` is valid.\n * Pass `newDeformerId === undefined` to detach (always legal).\n * Checks: part existence, undeclared deformer, and mesh-required-for-warp.\n */\nexport function validatePartAttach(\n deformers: IkiDeformer[],\n partId: string,\n parts: IkiPart[],\n newDeformerId: string | undefined,\n): void {\n // (1) Part must exist.\n const part = parts.find((p) => p.id === partId);\n if (part === undefined) {\n throw new Error(`parts: no part with id \"${partId}\"`);\n }\n\n // (2) Detach is always legal.\n if (newDeformerId === undefined) return;\n\n // (3) Deformer must be declared.\n const deformer = deformers.find((d) => d.id === newDeformerId);\n if (deformer === undefined) {\n throw new Error(\n `parts.\"${partId}\".deformer \"${newDeformerId}\" is not a declared deformer`,\n );\n }\n\n // (4) Warp deformer requires a mesh on the part.\n if (kindOf(deformer) === \"warp\" && part.mesh === undefined) {\n throw new Error(\n `parts.\"${partId}\".deformer \"${newDeformerId}\" is a warp deformer and requires a mesh`,\n );\n }\n}\n","/**\n * Alpha bounding-box scan shared by every auto-rig ingestion path.\n *\n * The scan itself is environment-free — it only needs indexable RGBA bytes — so\n * a browser editor (canvas `ImageData`) and the Node MCP server (a `sharp`\n * raw buffer) run the SAME code instead of two copies that have to be kept\n * byte-identical by hand. Only decoding differs between them.\n */\n\n/** Alpha at or above this counts as coverage; below it is treated as empty. */\nexport const ALPHA_BBOX_THRESHOLD = 8;\n\n/** Top-left origin, +y down — image space, not model space. */\nexport interface AlphaBbox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/**\n * Tight bounding box of every pixel with alpha >= {@link ALPHA_BBOX_THRESHOLD},\n * expanded 1px on each side (clamped to the image) for AA / extrude margin.\n *\n * Returns `null` when no pixel passes the threshold, leaving the \"empty layer\"\n * error to the caller: each ingestion path reports it with its own error type\n * and message.\n */\nexport function detectAlphaBbox(\n rgba: ArrayLike<number>,\n width: number,\n height: number,\n): AlphaBbox | null {\n let minX = width;\n let maxX = -1;\n let minY = height;\n let maxY = -1;\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const alpha = rgba[(y * width + x) * 4 + 3];\n if (alpha >= ALPHA_BBOX_THRESHOLD) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n }\n\n if (maxX === -1) return null;\n\n // Expand 1px each side, clamped to image bounds; the x2/y2 clamps make w/h\n // implicitly in-bounds (no separate w/h clamp needed).\n const x = Math.max(0, minX - 1);\n const y = Math.max(0, minY - 1);\n const x2 = Math.min(width - 1, maxX + 1);\n const y2 = Math.min(height - 1, maxY + 1);\n\n return { x, y, w: x2 - x + 1, h: y2 - y + 1 };\n}\n","/**\n * The alpha rules a layer set is measured by, and the pre-rig measurement of\n * that set, in one DOM-free copy — the way `detectAlphaBbox` is one.\n *\n * Both auto-rig hosts — the editor app (canvas `getImageData`) and\n * `@ikijs/mcp`'s `auto_rig_from_layers` (a `sharp` raw buffer) — hand\n * `createLayerSetMeasurer` the RGBA they decoded and rig what it measures, and\n * `@ikijs/mcp`'s other tools (`measure_turn_reference`, `measure_layers`, the\n * composer) read the same rules. Two copies would have to be kept identical by\n * hand, or the head a render measures back, or the nose core the composer\n * placed, would part from the one the rig was fitted to. Only decoding differs\n * between the hosts.\n */\n\nimport { detectAlphaBbox } from \"./alpha-bbox\";\nimport type { IrisStrand, LayerInput } from \"./auto-rig\";\n\n/** Half-height of the row band the head span is taken over, in px. Fixed at\n * ±10 rows rather than scaled to the image, and that is the convention: any\n * other measurement of head width meant to be compared with the one\n * `@ikijs/mcp`'s `measure_turn_reference` takes off a render — one taken off\n * layer alpha, a hand script — has to span the same band. Shared by that tool\n * and `createLayerSetMeasurer`, so the head it spans off the layers' alpha\n * union spans this band too. */\nexport const HEAD_BAND = 10;\n\n/** Alpha at or above this is opaque. Shared by `@ikijs/mcp`'s\n * `measure_turn_reference`, whose \"alpha\" foreground rule reads an engine\n * render's silhouette by it, and by the layer-alpha silhouette\n * `createLayerSetMeasurer` measures the head on, which has to follow that\n * rule to be comparable with a render. */\nexport const ALPHA_OPAQUE = 128;\n\n/**\n * A layer's dense core: the tight box of its pixels at alpha ≥ ALPHA_OPAQUE,\n * not grown. A soft-alpha part (a nose drawn as a shaded bump) is mostly\n * feather, and the core is the drawing a viewer reads inside it — `@ikijs/mcp`'s\n * composer sizes and places the nose by it, and `createLayerSetMeasurer` reads\n * the same core as the nose's `LayerInput.denseCore`, its turn landmark. It is\n * not the crop: that stays the alpha ≥ 8 box grown by 1 px (`detectAlphaBbox`).\n * `null` when no pixel reaches the threshold, a part painted wholly\n * translucent. A core that is a speck of its part (`isSpeckCore`) is not the\n * drawing either, and both readers fall back to the whole part, as they do for\n * `null`.\n */\nexport function denseCoreOf(\n rgba: ArrayLike<number>,\n width: number,\n height: number,\n): { x: number; y: number; w: number; h: number } | null {\n let minX = width;\n let minY = height;\n let maxX = -1;\n let maxY = -1;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n if (rgba[(y * width + x) * 4 + 3] >= ALPHA_OPAQUE) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n }\n if (maxX < 0) return null;\n return { x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1 };\n}\n\n/**\n * The fraction of its part's width, or of its height, under which a dense core\n * is a speck (`isSpeckCore`). Measured core/part ratios, width / height: the\n * hero's composed nose 0.72 / 0.76 (core 39×63 in a 54×83 crop), three\n * generated shaded-bump noses (the plugin's 0.11 nose prompt) 0.75–0.85 /\n * 0.79–0.91, `@ikijs/mcp`'s `writeSoftNose` test fixture 0.56 / 0.63 and its\n * `writeSoftNoseLayers` 0.40 / 0.40, a nostril mark ≤ 0.1. So the line sits at\n * least 1.6× under every real nose and fixture, and 2.5× over a speck. At the\n * line, sizing by the core would scale the whole part to 4× its layout width,\n * the largest blow-up `@ikijs/mcp`'s composer still accepts.\n */\nexport const SPECK_CORE_FRACTION = 0.25;\n\n/**\n * Whether a dense core is a speck of its part: narrower than\n * SPECK_CORE_FRACTION of the part's width, or shorter than that fraction of\n * its height (strictly `<`). Either dimension counts, because the core does\n * more than size a nose: its bottom row is the tip the composer places, and\n * its top-centre the rig's tilt pivot, so a sliver misplaces the nose as\n * surely as a speck mis-sizes it. A speck is a lone nostril mark or highlight,\n * not the drawing, and every reader falls back to the whole part: `@ikijs/mcp`'s\n * compose sizes and places its trimmed source part whole, and\n * `createLayerSetMeasurer` hands the rig no core, so the crop stands in.\n *\n * The two apply it to different pixels — compose to the source part before\n * resampling, the rig and `measure_layers` to the composed layer against its\n * crop — so their verdicts can part, but only for a core within about a\n * resampled pixel of the line, or one resampling pushes across ALPHA_OPAQUE.\n * Compose's report carries its source verdict when that was a speck, and\n * otherwise what the composed layer shows, so it warns of a parting either\n * way; `measure_layers` reports the layer alone.\n */\nexport function isSpeckCore(\n core: { w: number; h: number },\n part: { w: number; h: number },\n): boolean {\n return (\n core.w < SPECK_CORE_FRACTION * part.w ||\n core.h < SPECK_CORE_FRACTION * part.h\n );\n}\n\n/**\n * Outermost set pixels of `mask` across the row band `rowLo..rowHi` (clamped\n * to the image) — the silhouette span at that height. An empty band returns\n * `left > right`, which every caller has to check for.\n *\n * Shared by `@ikijs/mcp`'s `measure_turn_reference`, which spans a render's\n * head with it, and `createLayerSetMeasurer`, which spans the layers' alpha\n * union: the two heads are compared, so they have to be spanned the same way.\n */\nexport function foregroundSpan(\n mask: Uint8Array,\n width: number,\n height: number,\n rowLo: number,\n rowHi: number,\n): { left: number; right: number } {\n let left = width;\n let right = -1;\n for (let y = Math.max(0, rowLo); y <= Math.min(height - 1, rowHi); y++) {\n for (let x = 0; x < width; x++) {\n if (!mask[y * width + x]) continue;\n if (x < left) left = x;\n if (x > right) right = x;\n }\n }\n return { left, right };\n}\n\n/**\n * Half of a silhouette span, in px. The span is INCLUSIVE — `left` and `right`\n * are both foreground columns — so the head is `right - left + 1` px wide.\n * Shared by `@ikijs/mcp`'s `measure_turn_reference` and\n * `createLayerSetMeasurer`: the two head half-widths are compared against each\n * other, so they cannot be halved differently.\n */\nexport function headHalfOf(span: { left: number; right: number }): number {\n return (span.right - span.left + 1) / 2;\n}\n\n/** One decoded layer, as a host hands it to `LayerSetMeasurer.add`. */\nexport interface RgbaLayer {\n /** Canonical role, e.g. \"eye_L\" — the host has run `parseLayerRoles` on\n * the set already. */\n role: string;\n /** Original file name: the `LayerInput`'s own, and named in errors. */\n fileName: string;\n /** Straight-alpha RGBA, stride 4, `canvas.width × canvas.height` pixels —\n * canvas `ImageData.data` or a `sharp` raw buffer alike. */\n rgba: ArrayLike<number>;\n}\n\n/** A pixel darker than this share of the plate's median skin luminance is\n * line work: the jaw's outline, not its shading. */\nconst DARK_SHARE = 0.55;\n\n/**\n * The face plate's jaw line, per crop column: going down from the plate's\n * widest row, the canvas row of the last pixel of the first dark stroke met\n * (the jaw's outline where a neck runs on below it), or −1 where the column\n * leaves the paint first. `undefined` when no column meets a stroke — art\n * with no line work, which the generator then reads off its outline alone.\n */\nfunction jawRowsOf(\n rgba: ArrayLike<number>,\n canvasW: number,\n bbox: { x: number; y: number; w: number; h: number },\n rowLeft: Int32Array,\n rowRight: Int32Array,\n): number[] | undefined {\n const lum = (p: number) =>\n 0.299 * rgba[p * 4] + 0.587 * rgba[p * 4 + 1] + 0.114 * rgba[p * 4 + 2];\n const hist = new Uint32Array(256);\n let count = 0;\n let widest = bbox.y;\n let widestSpan = -1;\n for (let y = bbox.y; y < bbox.y + bbox.h; y++) {\n const span = rowRight[y] - rowLeft[y];\n if (span >= widestSpan) {\n widestSpan = span;\n widest = y;\n }\n for (let x = bbox.x; x < bbox.x + bbox.w; x++) {\n const p = y * canvasW + x;\n if (rgba[p * 4 + 3] < ALPHA_OPAQUE) continue;\n hist[Math.min(255, Math.round(lum(p)))]++;\n count++;\n }\n }\n if (count === 0) return undefined;\n let median = 0;\n for (let acc = 0; median < 255; median++) {\n acc += hist[median];\n if (acc * 2 >= count) break;\n }\n const dark = DARK_SHARE * median;\n const out: number[] = [];\n let found = false;\n for (let x = bbox.x; x < bbox.x + bbox.w; x++) {\n let row = -1;\n for (let y = widest + 1; y < bbox.y + bbox.h; y++) {\n const p = y * canvasW + x;\n if (rgba[p * 4 + 3] < ALPHA_OPAQUE) break;\n if (lum(p) >= dark) continue;\n let end = y;\n while (\n end + 1 < bbox.y + bbox.h &&\n rgba[((end + 1) * canvasW + x) * 4 + 3] >= ALPHA_OPAQUE &&\n lum((end + 1) * canvasW + x) < dark\n ) {\n end++;\n }\n row = end;\n break;\n }\n if (row >= 0) found = true;\n out.push(row);\n }\n return found ? out : undefined;\n}\n\n/**\n * Measures a layer set one decoded layer at a time, so a host holds one\n * full-canvas RGBA buffer at once, however many layers the set has. Call\n * `finish` once, after the last `add`: it hands back its own `layers` array,\n * which a later `add` would change.\n */\nexport interface LayerSetMeasurer {\n /**\n * Measure one layer while its `rgba` is in memory, keeping no reference to\n * it: only the set's opaque union, this layer's per-row opaque extent and\n * the `LayerInput` it returns outlive the call, so the host may drop `rgba`\n * as soon as it returns. Returns the layer's `LayerInput` — its crop\n * box, the face's `rowHalfWidths`, the face's, hair layers', body's and\n * arms' `rowRuns`, the nose's\n * `denseCore` unless that is a speck of its crop (`isSpeckCore`) — or\n * `null` for an empty layer, one with no pixel at or above\n * `ALPHA_BBOX_THRESHOLD`, which it records nothing for: the host reports\n * that with its own error. Throws, naming the file, when\n * `rgba` is not `width × height × 4` long; checking the decoded dimensions\n * is the host's job.\n */\n add(layer: RgbaLayer): LayerInput | null;\n /** The set's measurement, over every layer `add` recorded. The set must be\n * one `parseLayerRoles` accepted; otherwise this may throw, or measure a\n * partial set the generator then refuses. */\n finish(): LayerSetMeasurement;\n}\n\nexport interface LayerSetMeasurement {\n /** Every recorded layer's `LayerInput`, in `add` order. */\n layers: LayerInput[];\n /** The head's half-width at the eye row, canvas px: half the opaque\n * (alpha ≥ ALPHA_OPAQUE) union's span over ±HEAD_BAND rows about the row\n * of the iris centres, or of the eye centres without irises. Absent when\n * the union has no span there — a layer set painted translucent below that\n * threshold. */\n headHalfWidth?: number;\n /** Whether `headHalfWidth` is wider than the face plate, and so applied;\n * the face plate stands in for it otherwise, as the generator's own\n * fallback. */\n headHalfWidthApplied: boolean;\n /**\n * Ready to go into `generateIkiFromLayerSet`'s options, each key present\n * only when measured: `turnTargets.headHalfWidth` when it is applied (merge\n * the caller's own targets under it), `headEdges` — every layer's own\n * opaque extent in the same eye-row band, per side, in model x — with it,\n * and `strandEdges` whenever the set has `hair_front`, `iris_L` and `iris_R`\n * and a side measures one (`IrisStrand`).\n */\n turnOptions: {\n turnTargets?: { headHalfWidth: number };\n headEdges?: {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n };\n strandEdges?: { left?: IrisStrand; right?: IrisStrand };\n };\n}\n\n/**\n * The row the head's width is measured at: the mean of the iris centres, or of\n * the eye centres when the layer set has no irises. `@ikijs/mcp`'s\n * `measure_turn_reference` picks the same row off a render — it finds the\n * irises themselves — so the head it spans there is the head spanned here. Not\n * the generator's own eye row (`HeadFrame.eyeY` in `auto-rig/head.ts`, the eye\n * landmarks' mean model y, unrounded): this\n * is the canvas row of the crop centres, rounded, and one in place of the other\n * would move the measured head.\n */\nfunction eyeBandRowOf(layers: LayerInput[]): number {\n const centreY = (role: string): number | undefined => {\n const layer = layers.find((l) => l.role === role);\n return layer && layer.bbox.y + layer.bbox.h / 2;\n };\n const pairRow = (left: string, right: string): number | undefined => {\n const a = centreY(left);\n const b = centreY(right);\n return a === undefined || b === undefined ? undefined : (a + b) / 2;\n };\n const row = pairRow(\"iris_L\", \"iris_R\") ?? pairRow(\"eye_L\", \"eye_R\");\n if (row === undefined) {\n // eye_L/eye_R are required roles: a set without them is one\n // parseLayerRoles refuses, which `finish` requires the host to have run.\n throw new Error(\"auto-rig: no eye pair to measure the head width at\");\n }\n return Math.round(row);\n}\n\n/**\n * `foregroundSpan`, but over one layer's own already-reduced per-row\n * left/right (see `rowSpansByRole` in `createLayerSetMeasurer`) instead of a\n * pixel mask — the same row-band reduction, without re-scanning pixels.\n */\nfunction foregroundSpanOfRows(\n rowLeft: Int32Array,\n rowRight: Int32Array,\n rowLo: number,\n rowHi: number,\n): { left: number; right: number } {\n let left = Infinity;\n let right = -Infinity;\n for (\n let y = Math.max(0, rowLo);\n y <= Math.min(rowLeft.length - 1, rowHi);\n y++\n ) {\n if (rowLeft[y] < left) left = rowLeft[y];\n if (rowRight[y] > right) right = rowRight[y];\n }\n return { left, right };\n}\n\n/** The face plate's half-width, derived the way generateIkiFromLayerSet derives\n * it — off the `face` layer's cropped width — so the two agree on which head\n * is the wider one. */\nfunction facePlateHalfOf(layers: LayerInput[]): number {\n const face = layers.find((l) => l.role === \"face\");\n if (face === undefined) {\n // `face` is a required role: a set without it is one parseLayerRoles\n // refuses, which `finish` requires the host to have run.\n throw new Error(\"auto-rig: no face layer to measure the plate against\");\n }\n return face.cropW / 2;\n}\n\n/**\n * The narrowest `hair_front` run, as a fraction of an iris's painted width on\n * its centre row, that the strand scan takes as a strand. A run narrower than\n * this (strictly `<`; one exactly this wide is a strand) is hair detail and\n * counts as clear: the far iris may cross it on the turn, as intended. The\n * hero's row shows why: 5 px inside its 67 px side strand lies an 8 px wisp\n * the iris is painted 2 px under, and bounding the iris against that wisp cut\n * the −30 eye shift from ≈ 0.18 to 0.14.\n */\nconst STRAND_MIN_RUN_FRACTION = 0.5;\n\n/** The roles whose layers `add` records `rowRuns` for (see `LayerInput`). */\nconst ROW_RUN_ROLES: ReadonlySet<string> = new Set([\n \"face\",\n \"hair_front\",\n \"hair_back\",\n \"body\",\n \"arm_L\",\n \"arm_R\",\n]);\n\n/**\n * Start measuring a layer set on a `canvas`-sized canvas: the pass a host runs\n * between decoding its layers and `generateIkiFromLayerSet`. `add` each\n * decoded layer, then `finish`.\n *\n * Throws before allocating anything when `canvas.width` or `canvas.height` is\n * not a positive safe integer, or `width × height × 4` is not a safe integer.\n * How large a canvas to accept at all is each host's own limit.\n */\nexport function createLayerSetMeasurer(canvas: {\n width: number;\n height: number;\n}): LayerSetMeasurer {\n for (const field of [\"width\", \"height\"] as const) {\n const value = canvas[field];\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(\n `auto-rig: createLayerSetMeasurer: canvas.${field} must be a positive safe integer, got ${value}`,\n );\n }\n }\n const { width: canvasW, height: canvasH } = canvas;\n const rgbaLength = canvasW * canvasH * 4;\n if (!Number.isSafeInteger(rgbaLength)) {\n throw new Error(\n `auto-rig: createLayerSetMeasurer: canvas ${canvasW}x${canvasH} is too large: width × height × 4 = ${rgbaLength} is not a safe integer`,\n );\n }\n\n // Union of EVERY layer's opaque pixels — the silhouette the head half-width\n // is measured off in `finish`. Every layer folds in, so a body or an\n // accessory crossing the eye band widens the span; that is deliberate,\n // because a rest render of the finished rig shows the same union and\n // measures the same.\n const opaque = new Uint8Array(canvasW * canvasH);\n const layerInputs: LayerInput[] = [];\n // Per layer, per row: its OWN leftmost/rightmost opaque column (canvasW /\n // -1 where it has none that row) — recorded in the SAME pass as the union\n // fold, while the layer's decoded pixels are still live, rather than a\n // second decode pass. Read in `finish` once the eye row is known: each\n // layer's own extent in the eye-row band (`headEdges`), which the generator\n // lands through that layer's own deformation, and each iris's on its centre\n // row (`strandEdges`).\n const rowSpansByRole: {\n role: string;\n rowLeft: Int32Array;\n rowRight: Int32Array;\n }[] = [];\n\n function add({ role, fileName, rgba }: RgbaLayer): LayerInput | null {\n if (rgba.length !== rgbaLength) {\n throw new Error(\n `auto-rig: layer \"${fileName}\": rgba length ${rgba.length} is not ${canvasW}x${canvasH}x4 = ${rgbaLength}`,\n );\n }\n const bbox = detectAlphaBbox(rgba, canvasW, canvasH);\n if (bbox === null) return null;\n // Fold this layer into the silhouette AND record its own per-row extent\n // while its pixels are still here — one pass over the same pixels.\n const rowLeft = new Int32Array(canvasH).fill(canvasW);\n const rowRight = new Int32Array(canvasH).fill(-1);\n const rowRuns: number[][] | undefined = ROW_RUN_ROLES.has(role)\n ? []\n : undefined;\n for (let y = 0; y < canvasH; y++) {\n // Every opaque pixel lies inside the crop, so only its rows hold runs.\n let runs: number[] | undefined;\n if (rowRuns !== undefined && y >= bbox.y && y < bbox.y + bbox.h) {\n runs = [];\n rowRuns.push(runs);\n }\n let inRun = false;\n for (let x = 0; x < canvasW; x++) {\n const p = y * canvasW + x;\n const on = rgba[p * 4 + 3] >= ALPHA_OPAQUE;\n if (runs !== undefined && on !== inRun) {\n runs.push(x);\n inRun = on;\n }\n if (!on) continue;\n opaque[p] = 1;\n if (x < rowLeft[y]) rowLeft[y] = x;\n if (x > rowRight[y]) rowRight[y] = x;\n }\n if (runs !== undefined && inRun) runs.push(canvasW);\n }\n rowSpansByRole.push({ role, rowLeft, rowRight });\n const layer: LayerInput = {\n role,\n fileName,\n canvasW,\n canvasH,\n bbox,\n cropW: bbox.w,\n cropH: bbox.h,\n };\n if (rowRuns !== undefined) layer.rowRuns = rowRuns;\n if (role === \"face\") {\n // The plate's painted half-width on each of its crop rows — the same\n // alpha rule and halving as the head's own span, row by row (0 for a\n // row with no opaque pixel; a single opaque pixel IS a half-px row\n // here, where the head-span reads below treat a one-column band as\n // no span) — which give the plate's outline, the neck's plateau and\n // the ears' steps. The bbox admits alpha down to 8 while the span counts\n // alpha >= 128 only, so a row's span sits inside the crop and its\n // half never exceeds cropW / 2, the generator's bound.\n const rowHalfWidths: number[] = [];\n for (let y = bbox.y; y < bbox.y + bbox.h; y++) {\n rowHalfWidths.push(\n rowRight[y] >= rowLeft[y]\n ? headHalfOf({ left: rowLeft[y], right: rowRight[y] })\n : 0,\n );\n }\n layer.rowHalfWidths = rowHalfWidths;\n const jawRows = jawRowsOf(rgba, canvasW, bbox, rowLeft, rowRight);\n if (jawRows !== undefined) layer.jawRows = jawRows;\n } else if (role === \"nose\") {\n // The drawing inside a soft nose's feather, canvas px like `bbox` —\n // `rgba` is this layer's full-canvas buffer, so the core comes out in\n // the same coordinates as `bbox` and every other measurement here.\n // `null` (wholly translucent) or a speck of the crop (a lone nostril\n // mark, which `@ikijs/mcp`'s measure_layers flags on this same layer)\n // leaves `denseCore` unset, the generator falling back to the crop.\n const core = denseCoreOf(rgba, canvasW, canvasH);\n if (core !== null && !isSpeckCore(core, bbox)) layer.denseCore = core;\n }\n layerInputs.push(layer);\n return layer;\n }\n\n function finish(): LayerSetMeasurement {\n // The head's own half-width at the eye row, in canvas px, taken off the\n // layers' opaque union the way measure_turn_reference takes it off a render\n // (alpha rule, same row band, same halving) — so a rest render of this rig\n // measures the same span back. It is what the turn's shift targets are\n // fractions of; the generator's own fallback is the face plate, which is\n // narrower than the head the hair draws, and every shift then lands short.\n const eyeRow = eyeBandRowOf(layerInputs);\n const span = foregroundSpan(\n opaque,\n canvasW,\n canvasH,\n eyeRow - HEAD_BAND,\n eyeRow + HEAD_BAND,\n );\n // A layer set painted below the ALPHA_OPAQUE threshold (translucent art —\n // still above detectAlphaBbox's own, much lower, floor) has no confident\n // span here. That is not the same as having no head: fall back to the face\n // plate, same as a span that measures narrower than it below, rather than\n // refuse the whole rig over a union that is merely non-opaque.\n const headHalfWidth = span.right > span.left ? headHalfOf(span) : undefined;\n // ...but only when it IS wider than the plate. A hairless set, one whose\n // face plate is what the eye row is widest at, or one with no confident\n // span at all, measures a head the generator refuses (the silhouette\n // hold's zone would sit inside the plate) — and the right answer there is\n // the plate it falls back to, not no rig at all.\n const headHalfWidthApplied =\n headHalfWidth !== undefined &&\n headHalfWidth > facePlateHalfOf(layerInputs);\n\n // Every layer's own opaque extent in the same band — a companion to\n // headHalfWidth, only meaningful once it is actually applied (the\n // fallback path has no measured edge to report at all). The generator\n // lands each candidate through its OWN deformation and takes the\n // outermost LANDING, not just the outermost REST pixel, since which part\n // ends up furthest out after the turn can differ from which one drew\n // furthest out at rest. Model x (canvas x minus half the canvas width),\n // matching the generator's own placement of a layer (`boxOfLayer`).\n let headEdges:\n | {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n }\n | undefined;\n if (headHalfWidthApplied) {\n const bandLo = eyeRow - HEAD_BAND;\n const bandHi = eyeRow + HEAD_BAND;\n const left: { role: string; x: number }[] = [];\n const right: { role: string; x: number }[] = [];\n for (const { role, rowLeft, rowRight } of rowSpansByRole) {\n const own = foregroundSpanOfRows(rowLeft, rowRight, bandLo, bandHi);\n if (own.right <= own.left) continue; // no opaque pixel here at all\n left.push({ role, x: own.left - canvasW / 2 });\n right.push({ role, x: own.right - canvasW / 2 });\n }\n headEdges = { left, right };\n }\n\n // Each iris against the bangs' run it would slide under on the turn, on\n // ONE row — the one holding the iris's centre — under ONE rule (alpha >=\n // ALPHA_OPAQUE), a bangs run narrower than STRAND_MIN_RUN_FRACTION of that\n // iris's row width counting as clear. The iris's alpha-bbox (alpha >= 8, grown by a pixel) only\n // gives that row and where to start scanning, never an edge: every number\n // is the pixel boundary facing the neighbouring clear pixel, less half the\n // canvas, so each is the painted edge the way the generator's crop edges\n // (`boxOfLayer`) are. The scan decides with the very crop centres the\n // generator validates these edges against, so what it measures is always\n // accepted, on either side. A side's iris is whichever sits on that side,\n // the two paired by x rather than by role name. Measured whether or not\n // headHalfWidth is applied: the bound it feeds is the far iris against its\n // own strand, not the head's width.\n let strandEdges: { left?: IrisStrand; right?: IrisStrand } | undefined;\n const irisLayers = layerInputs\n .filter((l) => l.role === \"iris_L\" || l.role === \"iris_R\")\n .sort((a, b) => a.bbox.x + a.bbox.w / 2 - (b.bbox.x + b.bbox.w / 2));\n const hairFront = layerInputs.find((l) => l.role === \"hair_front\");\n const hairRuns = hairFront?.rowRuns;\n if (\n hairFront !== undefined &&\n hairRuns !== undefined &&\n irisLayers.length === 2\n ) {\n const hairTop = hairFront.bbox.y;\n const half = canvasW / 2;\n const strandOn = (\n iris: LayerInput,\n other: LayerInput,\n side: -1 | 1,\n ): IrisStrand | undefined => {\n const r = Math.floor(iris.bbox.y + iris.bbox.h / 2);\n // The iris's crop centre, canvas x (a pixel boundary for an even\n // width, a pixel's middle for an odd one), and the other's in model\n // x — the generator's placement of each (`boxOfLayer`).\n const centre = iris.bbox.x + iris.bbox.w / 2;\n const otherX = other.bbox.x + other.bbox.w / 2 - half;\n // The pixel just on THIS side of that centre: a run covering it\n // reaches outward past the centre, so its outer end is strictly\n // outward of it on either side, which a pixel chosen by one rounding\n // for both sides would not give.\n const c = side < 0 ? Math.ceil(centre) - 1 : Math.floor(centre);\n const span = rowSpansByRole.find((s) => s.role === iris.role)!;\n // An iris with no opaque pixel on its own centre row has no edge.\n if (span.rowRight[r] < span.rowLeft[r]) return undefined;\n // The row's strand pixels: hair_front's opaque runs on it, less every\n // run narrower than STRAND_MIN_RUN_FRACTION of this iris's painted\n // width there, which the whole scan below reads as clear. Runs are\n // judged whole, so the result is the same from either side.\n const minRun =\n STRAND_MIN_RUN_FRACTION * (span.rowRight[r] + 1 - span.rowLeft[r]);\n const strand = new Uint8Array(canvasW);\n // A row outside the bangs' crop has no opaque pixel of theirs.\n const runs =\n r >= hairTop && r < hairTop + hairRuns.length\n ? hairRuns[r - hairTop]\n : [];\n for (let k = 0; k < runs.length; k += 2) {\n if (runs[k + 1] - runs[k] >= minRun) {\n strand.fill(1, runs[k], runs[k + 1]);\n }\n }\n const strandAt = (x: number) =>\n x >= 0 && x < canvasW && strand[x] === 1;\n // The boundary between pixel x and its neighbour one step outward.\n const outerBoundary = (x: number) => (side < 0 ? x : x + 1) - half;\n let x = c;\n let runFace: number | null;\n if (!strandAt(c)) {\n // A clear centre (or one under a thin run only): the first strand\n // pixel outward starts the run, and its face-side boundary is\n // runFace.\n while (x >= 0 && x < canvasW && !strandAt(x)) x += side;\n if (x < 0 || x >= canvasW) return undefined; // no run outward\n runFace = outerBoundary(x - side);\n } else {\n // A covered centre: the run's face-side end is where it clears on\n // the face side — when that is strictly on this side of the other\n // iris's centre. A run still opaque there is a fringe spanning the\n // face, which has no face-side end on this side.\n let f = c - side;\n while (strandAt(f)) f -= side;\n const face = outerBoundary(f);\n runFace = side * (face - otherX) > 0 ? face : null;\n }\n // Outward to the run's outer end: its last opaque pixel's boundary\n // with the first clear one after it, or with the crop's edge.\n while (strandAt(x)) x += side;\n return {\n y: canvasH / 2 - (r + 0.5),\n irisOuter: (side < 0 ? span.rowLeft[r] : span.rowRight[r] + 1) - half,\n irisInner: (side < 0 ? span.rowRight[r] + 1 : span.rowLeft[r]) - half,\n runOuter: outerBoundary(x - side),\n runFace,\n };\n };\n const [low, high] = irisLayers;\n const left = strandOn(low, high, -1);\n const right = strandOn(high, low, 1);\n if (left !== undefined || right !== undefined) {\n strandEdges = {\n ...(left === undefined ? {} : { left }),\n ...(right === undefined ? {} : { right }),\n };\n }\n }\n\n return {\n layers: layerInputs,\n ...(headHalfWidth === undefined ? {} : { headHalfWidth }),\n headHalfWidthApplied,\n turnOptions: {\n ...(headHalfWidthApplied ? { turnTargets: { headHalfWidth } } : {}),\n ...(headEdges === undefined ? {} : { headEdges }),\n ...(strandEdges === undefined ? {} : { strandEdges }),\n },\n };\n }\n\n return { add, finish };\n}\n","import type { IkiTransformChannel } from \"@ikijs/format\";\n\n/**\n * Pure, binding-value logic for computing an endpoint (rest-to-posed delta or\n * ratio) when capturing a transform channel binding. No DOM, no @ikijs/engine —\n * the single home of the additive-vs-multiplicative rule, reused by both the\n * part and deformer capture paths.\n *\n * Additive channels (translateX, translateY, rotate, scaleX, scaleY) return the\n * delta: `posedValue - restValue`. The binding will multiply that delta across\n * the driven range.\n *\n * Opacity is multiplicative: returns the ratio `posedValue / restValue`. The\n * binding will multiply by that ratio across the driven range. When `restValue`\n * is 0 (a degenerate case: base opacity cannot be represented multiplicatively\n * since 0 * x ≡ 0), this returns 0 as a documented fallback — it does NOT\n * recover `posedValue` and is NOT unit-tested as an identity. The store layer\n * additionally skips an opacity capture when rest opacity is 0, surfacing an\n * editError.\n *\n * Deformer channels never include opacity (they use `IkiMatrixChannel`), so the\n * opacity branch is reached only for parts.\n *\n * Finiteness of the captured value is NOT validated here; the store's\n * `captureEndpoint` finite-value guard is the appropriate layer for that check.\n */\nexport function captureBindingEndpoint(\n channel: IkiTransformChannel,\n restValue: number,\n posedValue: number,\n): number {\n if (channel === \"opacity\") {\n return restValue === 0 ? 0 : posedValue / restValue;\n }\n return posedValue - restValue;\n}\n","import type { IkiUvRect } from \"@ikijs/format\";\n\nexport const ATLAS_PADDING = 2;\nexport const UV_INSET_PX = 0.5;\n\n/** Intrinsic pixel size of one decoded image; id is an editor-only stable key. */\nexport interface AtlasSource {\n id: string;\n width: number;\n height: number;\n}\n\n/** Sub-image pixel rect within the page, top-left origin, EXCLUDING the gutter. */\nexport interface AtlasPlacement {\n id: string;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface AtlasLayout {\n pageWidth: number;\n pageHeight: number;\n placements: AtlasPlacement[];\n padding: number;\n}\n\n/**\n * Deterministic shelf/row packer. Sources are sorted by id for stability so\n * identical inputs always produce an identical layout.\n *\n * Padding is one-sided: each placement reserves `padding` px on its RIGHT and\n * BOTTOM only. Page left/top edges need no gutter.\n *\n * pageWidth/pageHeight = tight bound (max x+width+padding, max y+height+padding).\n * Empty sources → { pageWidth: 0, pageHeight: 0, placements: [], padding }.\n * Throws a plain Error naming the offending source id on a non-finite or <= 0 dimension.\n */\nexport function packAtlas(\n sources: AtlasSource[],\n padding = ATLAS_PADDING,\n): AtlasLayout {\n for (const src of sources) {\n if (!isFinite(src.width) || src.width <= 0) {\n throw new Error(\n `packAtlas: source \"${src.id}\" has invalid width ${src.width}`,\n );\n }\n if (!isFinite(src.height) || src.height <= 0) {\n throw new Error(\n `packAtlas: source \"${src.id}\" has invalid height ${src.height}`,\n );\n }\n }\n\n if (sources.length === 0) {\n return { pageWidth: 0, pageHeight: 0, placements: [], padding };\n }\n\n // Stable sort by id so identical inputs always produce the same layout.\n const sorted = sources\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n\n // Target page width: ceil(sqrt(total padded area)), raised to a sane minimum.\n const totalArea = sorted.reduce(\n (sum, s) => sum + (s.width + padding) * (s.height + padding),\n 0,\n );\n const targetWidth = Math.max(\n Math.ceil(Math.sqrt(totalArea)),\n // Ensure at least the widest single source fits.\n Math.max(...sorted.map((s) => s.width + padding)),\n );\n\n const placements: AtlasPlacement[] = [];\n let shelfX = 0;\n let shelfY = 0;\n let shelfHeight = 0; // tallest padded item in the current row\n\n for (const src of sorted) {\n const paddedW = src.width + padding;\n const paddedH = src.height + padding;\n\n // Wrap to next row when the item doesn't fit on the current shelf.\n if (shelfX > 0 && shelfX + paddedW > targetWidth) {\n shelfY += shelfHeight;\n shelfX = 0;\n shelfHeight = 0;\n }\n\n placements.push({\n id: src.id,\n x: shelfX,\n y: shelfY,\n width: src.width,\n height: src.height,\n });\n\n shelfX += paddedW;\n if (paddedH > shelfHeight) shelfHeight = paddedH;\n }\n\n // Tight page bounds: max right/bottom padded edge across all placements.\n let pageWidth = 0;\n let pageHeight = 0;\n for (const p of placements) {\n const right = p.x + p.width + padding;\n const bottom = p.y + p.height + padding;\n if (right > pageWidth) pageWidth = right;\n if (bottom > pageHeight) pageHeight = bottom;\n }\n\n return { pageWidth, pageHeight, placements, padding };\n}\n\n/**\n * Convert a pixel placement into a UV rect, inset by `insetPx` on all four\n * edges and clamped to [0, 1] so the validator's bounds check always passes.\n */\nexport function uvRectFor(\n placement: AtlasPlacement,\n page: { width: number; height: number },\n insetPx = UV_INSET_PX,\n): IkiUvRect {\n const px = placement.x + insetPx;\n const py = placement.y + insetPx;\n const pw = placement.width - insetPx * 2;\n const ph = placement.height - insetPx * 2;\n\n const x = Math.max(0, px / page.width);\n const y = Math.max(0, py / page.height);\n const width = Math.min(1 - x, Math.max(0, pw / page.width));\n const height = Math.min(1 - y, Math.max(0, ph / page.height));\n\n return { x, y, width, height };\n}\n","import type {\n IkiMatrixDeformer,\n IkiMesh,\n IkiModel,\n IkiPart,\n IkiWarpDeformer,\n} from \"@ikijs/format\";\n\n/**\n * Pure, DOM-free factory helpers for creating new model objects from scratch.\n * Kept separate from `commands.ts` (which is edit-only) so that the \"add item\"\n * use-case has a dedicated, testable home with no mutation concerns.\n *\n * All factories accept the live model so they can derive a collision-free id and\n * a sensible draw-order / grid span without hard-coding sample assumptions.\n */\n\n/**\n * Return the first collision-free id in the shared part+deformer namespace.\n * Parts and deformers share a flat id namespace (validate.ts:692-706), so we\n * scan both arrays. Returns `base` if unused; otherwise tries `${base}_2`,\n * `${base}_3`, … until a free slot is found.\n *\n * Parameters are a separate namespace and are NOT included in the scan.\n */\nfunction generateUniqueId(model: IkiModel, base: string): string {\n const used = new Set<string>();\n for (const p of model.parts) {\n used.add(p.id);\n }\n for (const d of model.deformers ?? []) {\n used.add(d.id);\n }\n\n if (!used.has(base)) return base;\n\n let n = 2;\n while (true) {\n const candidate = `${base}_${n}`;\n if (!used.has(candidate)) return candidate;\n n++;\n }\n}\n\n/**\n * Generate the flat `[x0,y0, x1,y1, …]` rest-grid control points for a\n * regular axis-aligned lattice with `(cols+1)*(rows+1)` points, row-major.\n *\n * Row 0 is the TOP (y = maxY); y strictly decreases with row index.\n * Column 0 is left (x = minX); x strictly increases with column index.\n * This ordering satisfies the `IkiWarpGrid` rest-grid invariant\n * (packages/format/src/types.ts:178-196) required by the validator and\n * the engine's grid-sampling code.\n */\nfunction generateRegularGridPoints(\n cols: number,\n rows: number,\n minX: number,\n maxX: number,\n minY: number,\n maxY: number,\n): number[] {\n const pts: number[] = [];\n for (let row = 0; row <= rows; row++) {\n const t = row / rows;\n const y = maxY - t * (maxY - minY); // maxY at row 0, minY at row `rows`\n for (let col = 0; col <= cols; col++) {\n const s = col / cols;\n const x = minX + s * (maxX - minX); // minX at col 0, maxX at col `cols`\n pts.push(x, y);\n }\n }\n return pts;\n}\n\n/**\n * Create a minimal valid part with a collision-free id and a paint order one\n * above the current top-most part so it is immediately visible in the viewport.\n * Uses a distinct non-white blue tint so it is distinguishable from the canvas\n * background without requiring a texture.\n *\n * No optional keys (`texture`, `mesh`, `deformer`, `bindings`, `warps`) are set\n * — the format treats all of them as absent by default.\n */\nexport function createDefaultPart(model: IkiModel): IkiPart {\n const order = model.parts.length\n ? Math.max(...model.parts.map((p) => p.order)) + 1\n : 0;\n\n return {\n id: generateUniqueId(model, \"part\"),\n color: [0.45, 0.6, 0.85, 1],\n width: 150,\n height: 150,\n transform: { x: 0, y: 0 },\n order,\n };\n}\n\n/**\n * Create a minimal valid matrix deformer rooted at the canvas origin.\n * `kind` is omitted because the format treats its absence as \"matrix\" (the\n * default), keeping the serialised model compact.\n */\nexport function createDefaultMatrixDeformer(\n model: IkiModel,\n): IkiMatrixDeformer {\n return {\n id: generateUniqueId(model, \"deformer\"),\n pivot: { x: 0, y: 0 },\n };\n}\n\n/**\n * Create a regular grid mesh in part LOCAL space (±0.5 unit frame).\n *\n * Vertices span x ∈ [-0.5, 0.5] and y ∈ [-0.5, 0.5] (+y up, engine convention).\n * Row 0 is the TOP of the grid (y = +0.5); row index increases downward.\n * UVs are unit-square base coordinates: u = col/cols (0..1 left→right),\n * v = row/rows (0..1 top→bottom). The top row maps to v=0 because v and y\n * run in opposite directions — keeps textures upright without a post-flip.\n * The UV-to-texture remap (atlas rect) is applied later in SetPartMesh, not here.\n *\n * Index winding per cell: [BL, BR, TL] then [TL, BR, TR], matching the engine's\n * implicit-quad convention (see examples/editor/src/mesh-generator.ts).\n *\n * Bounds are validated BEFORE any array allocation because this factory runs\n * before SetPartMesh's parseIkiModel — an unbounded count would freeze the\n * editor before the format-level 65536 limit is ever reached.\n */\nexport function createGridMesh(cols: number, rows: number): IkiMesh {\n // Guard: cols/rows must be integers ≥1 and the vertex count must fit within\n // the format limit of 65536 vertices (packages/format/src/validate.ts parseMesh).\n if (\n !Number.isInteger(cols) ||\n cols < 1 ||\n !Number.isInteger(rows) ||\n rows < 1 ||\n (cols + 1) * (rows + 1) > 65536\n ) {\n throw new Error(\n \"createGridMesh: cols and rows must be integers >= 1 with (cols+1)*(rows+1) <= 65536\",\n );\n }\n\n const colVerts = cols + 1;\n const rowVerts = rows + 1;\n\n const vertices: number[] = [];\n const uvs: number[] = [];\n\n // Row 0 is TOP (y = +0.5). Row `rows` is BOTTOM (y = -0.5).\n // Column 0 is left (x = -0.5). Column `cols` is right (x = +0.5).\n for (let row = 0; row < rowVerts; row++) {\n const t = row / rows;\n const y = 0.5 - t; // +0.5 at row 0, -0.5 at row `rows`\n const v = t; // 0 at top row, 1 at bottom row\n\n for (let col = 0; col < colVerts; col++) {\n const s = col / cols;\n const x = -0.5 + s; // -0.5 at col 0, +0.5 at col `cols`\n const u = s; // 0 at left col, 1 at right col\n\n vertices.push(x, y);\n uvs.push(u, v);\n }\n }\n\n // Two triangles per cell: [BL, BR, TL] then [TL, BR, TR].\n const indices: number[] = [];\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const tl = row * colVerts + col;\n const tr = row * colVerts + col + 1;\n const bl = (row + 1) * colVerts + col;\n const br = (row + 1) * colVerts + col + 1;\n\n indices.push(bl, br, tl);\n indices.push(tl, br, tr);\n }\n }\n\n return { vertices, uvs, indices };\n}\n\n/**\n * Create a 4×4-cell warp deformer whose rest grid spans a quarter of the\n * canvas in each direction (`±canvas.width/4` × `±canvas.height/4`). For the\n * 1000-unit sample canvas this gives x,y ∈ [−250, 250], which is large enough\n * to cover a typical face part without spilling to the edge.\n *\n * `warps` is omitted — the format treats its absence as \"rest grid only\", so\n * the deformer is immediately usable without authored keyforms.\n * `parent` is omitted — the deformer is placed at root; the caller may\n * reparent it via `SetDeformerParent` after creation.\n */\nexport function createDefaultWarpDeformer(model: IkiModel): IkiWarpDeformer {\n const hx = model.canvas.width / 4;\n const hy = model.canvas.height / 4;\n\n return {\n kind: \"warp\",\n id: generateUniqueId(model, \"warp\"),\n grid: {\n cols: 4,\n rows: 4,\n points: generateRegularGridPoints(4, 4, -hx, hx, -hy, hy),\n },\n };\n}\n","/**\n * How far each region of a head moves at the extremes of each head\n * parameter. The rules are a 2D rig's usual ones. A turn is parallax, not a\n * reshaped face: the face plate translates, the features in front of it lead\n * it by their depth (the nose most), the chin leads it too, the front hair\n * rides the face, the back hair drifts a little the other way, and the torso,\n * which the head hangs from, follows it only a little (`body.ts`). A nod is\n * the same parallax vertically; a roll turns the head about the chin. Every\n * curve is linear in its parameter, so one keyform per extreme carries it\n * exactly.\n *\n * The magnitudes are our own values, `PROFILE_VALUES`: the head's picked by\n * eye on our own characters, the body's still provisional\n * (`packages/editor/AUTO-RIG.md`); what the rig reads — `TURN`, `NOD`,\n * `ROLL_DEG`, `AMPLITUDE` and `BODY` — is derived from them.\n * Lengths are in the head unit `hh`, the eye row → chin tip at rest.\n */\n\n/** The values the profile is derived from, each at its parameter's extreme\n * (±30 for the head angles). */\nexport interface ProfileValues {\n /** AngleX: the face plate translates this far, hh. */\n slide: number;\n /** AngleX: a feature on the face — an eye, a brow, the mouth, the chin\n * tip — leads the plate by this, hh. */\n lead: number;\n /** AngleX: the nose leads the plate this many times `lead`. */\n noseDepth: number;\n /** AngleX: the front hair rides the face at this share of its slide. */\n hairFollow: number;\n /** AngleX: the far eye and the far ear narrow to 1 − fore of their width,\n * the near eye widens to 1 + fore / 2; each eye's and brow's lead scales\n * with its eye's width. */\n fore: number;\n /** The back hair takes this share of the plate's motion: against it on the\n * turn, with it on the nod. */\n backShare: number;\n /** AngleX: the far ear's outer edge moves this share of the plate's slide\n * (the near ear rides the head). */\n earFar: number;\n /** AngleY −30 (looking down): the plate's top drops this far, hh. */\n nodDown: number;\n /** AngleY +30 (looking up): the plate rises this far, whole, hh. */\n nodUp: number;\n /** AngleY: a feature on the face leads the plate's nod at mid-face by this\n * either way, hh; the nose `noseDepth` times it. */\n nodLead: number;\n /** AngleY −30: the chin drops this share of the plate's top. */\n chinShare: number;\n /** AngleZ ±30 rolls the head this many degrees about the chin. */\n rollDeg: number;\n /** The iris travels this many iris widths sideways, half as far up and\n * down. */\n gaze: number;\n /** How far the upper lid comes down, over the eye's height. */\n blink: number;\n /** A single mouth drawing opens to this height over its rest width. */\n mouthOpen: number;\n /** The mouth widens to this much of its width open. */\n mouthWiden: number;\n /** A brow raises and lowers this far, hh. */\n brow: number;\n /** A breath lifts the shoulders this far, hh, and the head two thirds of\n * it. */\n breath: number;\n /** A hair tip travels this far at full sway (±20), hh. */\n sway: number;\n /** At Cheek 0 the blush shows at this opacity; at Cheek 1, as drawn. */\n blushRest: number;\n // The six body values each move the body warp's weight-1 band (`body.ts`),\n // fading to nothing at the hips.\n /** BodyAngleX ±10: the upper body slides this far, hh. */\n bodySlide: number;\n /** BodyAngleX ±10: the upper body narrows by this share of its width,\n * about the body's centre, either way. */\n bodyNarrow: number;\n /** BodyAngleY +10: the upper body rises this far, hh; −10 bows it as far. */\n bodyBow: number;\n /** BodyAngleZ ±10 rolls the upper body this many degrees about the hips. */\n bodyRoll: number;\n /** AngleX ±30: the body follows the head's turn at this share of\n * BodyAngleX ±10. */\n bodyFollowX: number;\n /** AngleZ ±30: the body follows the head's tilt at this share of\n * `bodyRoll`. */\n bodyFollowZ: number;\n}\n\n/** The values. The head's, `slide` to `blushRest`: round numbers picked by\n * eye on our own characters (Bob and the long-haired one), each against its\n * neighbours on a coarse grid in a blind A/B judged by a fresh agent and by\n * us (2026-10); `AUTO-RIG.md` has the record. The six body values,\n * `bodySlide` to `bodyFollowZ`, are provisional: our own but not yet picked\n * by eye, which they will be on Bob's full body (full-body slice 3), never\n * off a sample. */\nexport const PROFILE_VALUES: ProfileValues = {\n slide: 0.12,\n lead: 0.1,\n noseDepth: 2,\n hairFollow: 1,\n fore: 0.2,\n backShare: 0.1,\n earFar: 0.5,\n nodDown: 0.18,\n nodUp: 0.1,\n nodLead: 0.06,\n chinShare: 0.75,\n rollDeg: 14,\n gaze: 0.2,\n blink: 0.6,\n mouthOpen: 0.8,\n mouthWiden: 1.2,\n brow: 0.15,\n breath: 0.03,\n sway: 0.08,\n blushRest: 0.4,\n bodySlide: 0.1,\n bodyNarrow: 0.05,\n bodyBow: 0.06,\n bodyRoll: 4,\n bodyFollowX: 0.3,\n bodyFollowZ: 0.3,\n};\n\n/** What the rig reads, derived from `v`. */\nexport function deriveProfile(v: ProfileValues) {\n const farLead = v.lead * (1 - v.fore / 2);\n const nearLead = v.lead * (1 + v.fore / 2);\n /** AngleX ±30, hh along the turn (\"far\" = the side the face turns toward). */\n const turn = {\n /** The face plate's translation. */\n face: v.slide,\n /** The chin tip's lead over the plate. */\n chinLead: v.lead,\n /** The plate's width at full turn: eye and cheek rows, then the jaw. The\n * plate translates; it does not narrow. */\n widthUpper: 1,\n widthJaw: 1,\n eyeFar: v.slide + farLead,\n eyeNear: v.slide + nearLead,\n /** Each eye's width at full turn, about its own centre. */\n eyeFarScale: 1 - v.fore,\n eyeNearScale: 1 + v.fore / 2,\n browFar: v.slide + farLead,\n browNear: v.slide + nearLead,\n nose: v.slide + v.noseDepth * v.lead,\n mouth: v.slide + v.lead,\n mouthWidth: 1,\n /** The mouth's far corner rises (its near end drops) by this much: it\n * stays level. */\n mouthTiltDeg: 0,\n /** The front hair (bangs and side locks) rides the face at this share of\n * its translation. */\n hairFollow: v.hairFollow,\n /** The head's outline at the eye row holds: where the front hair draws\n * it, its outer edge follows the face this much on a row where no back\n * hair paints behind that edge. Where back hair does, the edge rides\n * further, as far as that back hair stays behind it through the turn and\n * the nod, up to the face's follow there (`hairFollow`; over the far\n * eye's rows, as far as that eye's outer corner goes). On the cap (the\n * rows above the eyes) it follows less where the turn would otherwise\n * carry it further outside its back hair than the nod alone does. */\n outlineFollow: 0,\n /** The back hair's slight counter-motion. */\n hairBack: -v.backShare * v.slide,\n /** The ears lag the plate: the far one's outer edge moves this share of\n * its slide; the near one rides the head. */\n earFar: v.earFar,\n earNear: 1,\n /** The far ear's width at full turn, about its outer edge, where the head\n * leaves it room; less where it does not. */\n earFarScale: 1 - v.fore,\n };\n // The plate's nod halfway between its top and the chin, looking down.\n const mid = (v.nodDown * (1 + v.chinShare)) / 2;\n const feature = (depth: number) => ({\n up: -(v.nodUp + depth * v.nodLead),\n down: mid + depth * v.nodLead,\n });\n /** AngleY: screen displacement, hh, + = DOWN, at +30 (looking up) and −30\n * (looking down). */\n const nod = {\n faceTop: { up: -v.nodUp, down: v.nodDown },\n chin: { up: -v.nodUp, down: v.chinShare * v.nodDown },\n eye: feature(1),\n /** Eye height at the extreme, about the eye's centre: it holds. */\n eyeHeight: { up: 1, down: 1 },\n brow: feature(1),\n nose: feature(v.noseDepth),\n mouth: feature(1),\n hairFront: { up: -v.hairFollow * v.nodUp, down: v.hairFollow * v.nodDown },\n /** The front hair's cap top: half the plate's rise looking up; looking\n * down the plate's top, which the rig slides only as far as the back\n * hair covers the crown behind it. */\n hairFrontTop: { up: -v.nodUp / 2, down: v.nodDown },\n hairBack: { up: -v.backShare * v.nodUp, down: v.backShare * v.nodDown },\n };\n /** Everything else, at each parameter's extreme. */\n const amplitude = {\n /** Iris travel, in iris widths. */\n gazeX: v.gaze,\n gazeY: v.gaze / 2,\n /** How far the upper lid comes down, over the eye's height. */\n blink: v.blink,\n /** A single mouth drawing opens to this height over its rest width. */\n mouthOpenHeight: v.mouthOpen,\n /** The mouth widens this much open. */\n mouthOpenWidth: v.mouthWiden,\n /** Brow raise / lower, hh. */\n brow: v.brow,\n /** Breath lifts the shoulders and the head, hh. */\n breathBody: v.breath,\n breathHead: (v.breath * 2) / 3,\n /** Hair tip travel at full sway (±20), hh. */\n sway: v.sway,\n /** The blush's opacity at Cheek 0; at Cheek 1 it is as drawn. */\n blushRest: v.blushRest,\n /** The neck under the face reaches this far above the jaw, hh — what the\n * chin uncovers as it slides off it: half again the chin's full-turn\n * slide, to the next 0.05. */\n hiddenNeck: Math.ceil(30 * (v.slide + v.lead) - 1e-9) / 20,\n };\n /** The body warp's motions (`body.ts`), each at its parameter's extreme:\n * BodyAngleX/Y/Z ±10, the follow at AngleX/AngleZ ±30. */\n const body = {\n /** BodyAngleX: the upper body's slide, hh. */\n slide: v.bodySlide,\n /** BodyAngleX: how much narrower the upper body gets, either way. */\n narrow: v.bodyNarrow,\n /** BodyAngleY: the upper body's rise (+) or bow (−), hh. */\n bow: v.bodyBow,\n /** BodyAngleZ: the upper body's roll about the hips, degrees. */\n rollDeg: v.bodyRoll,\n /** AngleX: the body's follow, as a share of BodyAngleX's motion. */\n followX: v.bodyFollowX,\n /** AngleZ: the body's follow, as a share of its roll. */\n followZ: v.bodyFollowZ,\n /** The roll the follow gives the body at AngleZ ±30, degrees: β, the\n * share of `ROLL_DEG` the head's own roll leaves to the body. */\n followRoll: v.bodyFollowZ * v.bodyRoll,\n };\n return {\n TURN: turn,\n NOD: nod,\n ROLL_DEG: v.rollDeg,\n AMPLITUDE: amplitude,\n BODY: body,\n };\n}\n\nexport const { TURN, NOD, ROLL_DEG, AMPLITUDE, BODY } =\n deriveProfile(PROFILE_VALUES);\n\n/**\n * Per-character tuning, starting from the profile. `turn`, `featureLead` and\n * `sway` multiply the profile (1 = the profile); `hairFollow`,\n * `outlineFollow` and `blink` replace its value. `AUTO-RIG.md` lists the\n * ranges that read well.\n */\nexport interface RigStyle {\n /** The whole turn — plate, features and hair. Ignored when a\n * `turnTargets.eyeShift` is given, which fits it instead. */\n turn?: number;\n /** How far the features lead the plate. */\n featureLead?: number;\n /** The front hair's share of the face's turn. */\n hairFollow?: number;\n /** Its outer edge's share, where the front hair draws the head's outline\n * and no back hair paints behind that edge (profile 0: the outline holds;\n * `hairFollow` rides it whole). Where back hair does, the edge rides\n * further, as far as that back hair stays behind it through the turn and\n * the nod, up to the front hair's follow there (`hairFollow`; over the\n * far eye's rows, as far as that eye's outer corner goes). On the cap\n * (the rows above the eyes) the edge follows less where the turn would\n * otherwise carry it further outside its back hair than the nod alone\n * does. */\n outlineFollow?: number;\n /** How far the upper lid comes down, over the eye's height. */\n blink?: number;\n /** Hair sway amplitude. */\n sway?: number;\n}\n\n/** Every knob `RigStyle` has: a caller's style names only these. */\nexport const STYLE_KNOBS: readonly (keyof RigStyle)[] = [\n \"turn\",\n \"featureLead\",\n \"hairFollow\",\n \"outlineFollow\",\n \"blink\",\n \"sway\",\n];\n\nexport interface ResolvedStyle {\n turn: number;\n featureLead: number;\n hairFollow: number;\n outlineFollow: number;\n blink: number;\n sway: number;\n}\n\n/** Style knobs resolved against the profile; `check` names a bad one. */\nexport function resolveStyle(\n style: RigStyle | undefined,\n check: (key: string, v: unknown, lo: number, hi: number) => number,\n): ResolvedStyle {\n const s = style ?? {};\n const get = (key: keyof RigStyle, def: number, lo: number, hi: number) =>\n s[key] === undefined ? def : check(`style.${key}`, s[key], lo, hi);\n return {\n turn: get(\"turn\", 1, 0, 3),\n featureLead: get(\"featureLead\", 1, 0, 3),\n hairFollow: get(\"hairFollow\", TURN.hairFollow, 0, 2),\n outlineFollow: get(\"outlineFollow\", TURN.outlineFollow, 0, 2),\n blink: get(\"blink\", AMPLITUDE.blink, 0.1, 1),\n sway: get(\"sway\", 1, 0, 5),\n };\n}\n","/**\n * The public shapes of the auto-rig: what a host hands `generateIkiFromLayerSet`\n * and what the turn solve reports back. Pixel measurement lives in\n * `layer-measure.ts`; everything here is already-decoded geometry.\n */\n\nimport { TURN, type RigStyle } from \"./profile\";\n\nconst round2 = (v: number) => Math.round(v * 100) / 100;\n\n/** One role layer, as a host measured it off its decoded pixels. */\nexport interface LayerInput {\n /** Canonical role (see `parseLayerRoles`); becomes the part ids\n * `partIdsOfRole` lists. */\n role: string;\n fileName: string;\n canvasW: number;\n canvasH: number;\n /** Alpha bounding box in canvas px (y down) — the crop the atlas holds. */\n bbox: { x: number; y: number; w: number; h: number };\n cropW: number;\n cropH: number;\n /** Face only: half the opaque span of each crop row, canvas px (0 = none). */\n rowHalfWidths?: number[];\n /** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` only:\n * per crop row, its opaque (alpha ≥ 128) runs as a flat list of canvas\n * columns `[start0, end0, start1, end1, …]`, each end exclusive (`[]` for a\n * row with none). The actual pixels, so a gap in the hair is a gap here:\n * the turn and the nod read off it where back hair is painted behind the\n * front hair, and the crown's turn reads the face's so it never bares skin.\n * The body's place the hips (where it splits into legs), and an arm's place\n * its shoulder and elbow pivots. */\n rowRuns?: number[][];\n /** Nose only: the tight box of its alpha ≥ 128 pixels, canvas px. */\n denseCore?: { x: number; y: number; w: number; h: number };\n /** Face only: per crop column, the canvas row of the last pixel of the\n * first dark stroke met going down from the plate's widest row (the jaw's\n * outline, across a neck), or −1 where the column leaves the paint first.\n * Where the head ends and the neck the body keeps begins. */\n jawRows?: number[];\n}\n\n/**\n * One side's iris against the `hair_front` run it would slide under on the\n * turn, on the row holding the iris centre. Model coordinates: x is canvas x\n * minus half the canvas width, y is half the canvas height minus canvas y.\n */\nexport interface IrisStrand {\n y: number;\n irisOuter: number;\n irisInner: number;\n runOuter: number;\n /** The run's face-side end; `null` for a fringe spanning the face. */\n runFace: number | null;\n}\n\n/**\n * Head-turn cues at ±30°, as `measure_turn_reference` reads them off a front\n * and a turned image. Shifts are fractions of the head half-width, taken as\n * magnitudes: that tool signs them by the reference's turn direction.\n */\nexport interface TurnTargets {\n eyeShift?: number;\n farEyeRatio?: number;\n silhouetteRatio?: number;\n noseShift?: number;\n mouthShift?: number;\n /** The head half-width the shifts are fractions of, canvas px. */\n headHalfWidth?: number;\n}\n\n/** A turn target this layer set cannot reach, or turn input that is malformed. */\nexport class TurnTargetError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TurnTargetError\";\n }\n}\n\n/**\n * Art geometry the rig cannot build on — today a body whose hips leave no row\n * line under its pivots, or too little room for its motion (`body.ts`). A fact about the layers, not a bug, so a\n * host reports it as an input error.\n */\nexport class LayerGeometryError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LayerGeometryError\";\n }\n}\n\n/**\n * The profile's own turn (`profile.ts`), in the cues' units — what a rig with\n * no `turnTargets` renders on a head whose silhouette at the eye row is back\n * hair about 1 hh (eye row → chin) wide. eyeShift: the eye pair's mean shift\n * at ±30 less the back hair's drift, over a 1 hh head half-width.\n * farEyeRatio: the far eye's width over the near one's. silhouetteRatio: the\n * silhouette holds its width.\n *\n * With no target given the rig renders the profile itself, whatever the cues\n * then read on its art (a head whose side locks draw its silhouette, and ride\n * the face, reads a smaller eyeShift); a given target is fitted.\n */\nexport const DEFAULT_TURN_TARGETS: Readonly<\n Required<Pick<TurnTargets, \"eyeShift\" | \"farEyeRatio\" | \"silhouetteRatio\">>\n> = Object.freeze({\n eyeShift: round2((TURN.eyeFar + TURN.eyeNear) / 2 - TURN.hairBack),\n farEyeRatio: round2(TURN.eyeFarScale / TURN.eyeNearScale),\n silhouetteRatio: 1,\n});\n\n/** How far each feature family stands in front of the plate, as the depth a\n * rotation would need to give its shift at ±30 (shift / sin 30°), in head\n * half-widths — the nose leads the mouth and the mouth the eyes. */\nexport interface TurnDepths {\n eye: number;\n nose: number;\n mouth: number;\n}\n\n/** How much of a far iris's painted row the bangs' run covers. */\nexport interface StrandOverlap {\n /** The turn stop (AngleX, degrees) where the coverage is largest. */\n deg: number;\n /** Covered width there, canvas px. */\n px: number;\n /** The same in head half-widths. */\n hh: number;\n /** Covered width at rest. */\n restPx: number;\n /** Whether the iris went no deeper under the run than it is painted.\n * Always `false` for a fringe spanning the face (`runFace: null`), which\n * has no side to keep the iris clear of. */\n held: boolean;\n}\n\nexport interface TurnSolveReport {\n /** The curvature the plate would need to put the eyes as far in front of\n * its edge as their lead over it does, as a radius, canvas px. */\n radius: number;\n /** The measured head half-width, canvas px, which the shift cues are\n * fractions of — on a set with none measured (hairless) the face crop's\n * half-width, while the cues are then fractions of the plate's painted\n * half-width at the eye row. */\n holdBase: number;\n depths: TurnDepths;\n /** What the rig renders at ±30° (mean of both directions). */\n achieved: { eyeShift: number; farEyeRatio: number; silhouetteRatio: number };\n /** Targets cut down to what this layer set can do. */\n clamped: (keyof TurnTargets)[];\n strandOverlap?: { left?: StrandOverlap; right?: StrandOverlap };\n}\n\nexport interface HeadEdges {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n}\n\nexport interface GenerateOptions {\n turnTargets?: TurnTargets;\n /** Per-character tuning from the profile's defaults (`profile.ts`). */\n style?: RigStyle;\n onTurnSolved?: (report: TurnSolveReport) => void;\n headEdges?: HeadEdges;\n strandEdges?: { left?: IrisStrand; right?: IrisStrand };\n}\n","/**\n * The roles a layer set may carry, in draw order (back to front), and the\n * file-name → role parse every host runs before measuring.\n */\n\n/** Which turn family a role rides: each family is baked on its own grid. */\nexport type Family =\n | \"face\"\n | \"eye_L\"\n | \"eye_R\"\n | \"brow_L\"\n | \"brow_R\"\n | \"nose\"\n | \"mouth\"\n | \"hair_front\"\n | \"hair_back\"\n | \"body\"\n | \"arm\";\n\nexport interface RoleSpec {\n role: string;\n family: Family;\n required?: true;\n /** The part ids the role's layer becomes, back to front; absent, the\n * role's own id. */\n parts?: readonly string[];\n}\n\n/** Back to front. `@ikijs/mcp`'s composer draws in the same order. */\nexport const ROLE_TABLE: readonly RoleSpec[] = [\n { role: \"hair_back\", family: \"hair_back\" },\n { role: \"body\", family: \"body\" },\n { role: \"arm_L\", family: \"arm\", parts: [\"arm_L\", \"forearm_L\"] },\n { role: \"arm_R\", family: \"arm\", parts: [\"arm_R\", \"forearm_R\"] },\n { role: \"face\", family: \"face\", required: true },\n { role: \"blush_L\", family: \"face\" },\n { role: \"blush_R\", family: \"face\" },\n { role: \"nose\", family: \"nose\" },\n { role: \"mouth\", family: \"mouth\", required: true },\n { role: \"mouth_open\", family: \"mouth\" },\n { role: \"eye_L\", family: \"eye_L\", required: true },\n { role: \"eye_R\", family: \"eye_R\", required: true },\n { role: \"iris_L\", family: \"eye_L\" },\n { role: \"iris_R\", family: \"eye_R\" },\n { role: \"pupil_L\", family: \"eye_L\" },\n { role: \"pupil_R\", family: \"eye_R\" },\n { role: \"highlight_L\", family: \"eye_L\" },\n { role: \"highlight_R\", family: \"eye_R\" },\n { role: \"lash_lower_L\", family: \"eye_L\" },\n { role: \"lash_lower_R\", family: \"eye_R\" },\n { role: \"lash_L\", family: \"eye_L\" },\n { role: \"lash_R\", family: \"eye_R\" },\n { role: \"brow_L\", family: \"brow_L\" },\n { role: \"brow_R\", family: \"brow_R\" },\n { role: \"hair_front\", family: \"hair_front\" },\n];\n\nexport const REQUIRED_ROLES: readonly string[] = ROLE_TABLE.filter(\n (r) => r.required,\n).map((r) => r.role);\n\nconst SPEC_BY_ROLE = new Map(ROLE_TABLE.map((r, i) => [r.role, { ...r, i }]));\n\nexport function roleSpec(role: string): RoleSpec & { i: number } {\n const spec = SPEC_BY_ROLE.get(role);\n if (spec === undefined) throw new Error(`auto-rig: unknown role \"${role}\"`);\n return spec;\n}\n\n/** The part ids a `role`'s layer becomes, back to front: every one of them\n * takes its texture from the layer's crop. Throws on an unknown role. */\nexport function partIdsOfRole(role: string): readonly string[] {\n return roleSpec(role).parts ?? [role];\n}\n\nconst ROLE_BY_PART = new Map(\n ROLE_TABLE.flatMap((r) => (r.parts ?? []).map((p) => [p, r.role] as const)),\n);\n\n/** The role whose layer a part comes from; an id no role lists as a part is\n * its own role. */\nexport function roleOfPart(partId: string): string {\n return ROLE_BY_PART.get(partId) ?? partId;\n}\n\n/** Spelling variants seen on real layer sets, after the case and separator\n * normalisation below. */\nconst ALIASES: Record<string, string> = {\n eyebrow_L: \"brow_L\",\n eyebrow_R: \"brow_R\",\n eye_white_L: \"eye_L\",\n eye_white_R: \"eye_R\",\n};\n\n/** The role a file name names: without its extension, lower-cased, hyphens\n * and spaces as underscores, a trailing `_l` / `_r` side upper-cased, then\n * the aliases (\"Eye-L.png\" → \"eye_L\", \"eyebrow_R.png\" → \"brow_R\"). A PSD\n * layer name (no extension) names its role the same way. */\nfunction roleOf(fileName: string): string {\n const role = fileName\n .replace(/\\.[^.]+$/, \"\")\n .toLowerCase()\n .replace(/[-\\s]+/g, \"_\")\n .replace(/_([lr])$/, (_, s: string) => `_${s.toUpperCase()}`);\n return ALIASES[role] ?? role;\n}\n\n/** An arm hangs from the body's shoulder (`arms.ts`): throws on an arm role\n * among `roles` without a `body`. */\nexport function checkArmsHaveBody(roles: Iterable<string>): void {\n const has = new Set(roles);\n if (has.has(\"body\")) return;\n const arm = ROLE_TABLE.find((r) => r.family === \"arm\" && has.has(r.role));\n if (arm !== undefined) {\n throw new Error(\n `auto-rig: ${arm.role} needs a body layer (an arm hangs from the body's shoulder)`,\n );\n }\n}\n\n/**\n * Map file names to roles. Throws on an unknown role, a role named twice, a\n * required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, or an arm\n * without a body.\n */\nexport function parseLayerRoles(\n fileNames: string[],\n): { role: string; fileName: string }[] {\n const seen = new Map<string, string>();\n const out: { role: string; fileName: string }[] = [];\n for (const fileName of fileNames) {\n const role = roleOf(fileName);\n if (!SPEC_BY_ROLE.has(role)) {\n throw new Error(\n `auto-rig: \"${fileName}\" names no known role (expected one of ${ROLE_TABLE.map((r) => r.role).join(\", \")})`,\n );\n }\n const prior = seen.get(role);\n if (prior !== undefined) {\n throw new Error(\n `auto-rig: role \"${role}\" is named twice (\"${prior}\" and \"${fileName}\")`,\n );\n }\n seen.set(role, fileName);\n out.push({ role, fileName });\n }\n const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));\n if (missing.length > 0) {\n throw new Error(\n `auto-rig: missing required role${missing.length > 1 ? \"s\" : \"\"} ${missing.join(\", \")}`,\n );\n }\n checkArmsHaveBody(seen.keys());\n return out;\n}\n","/**\n * `generateIkiFromLayerSet`: role layers in, a rigged `.iki` out.\n *\n * The rig's shape is a 2D head rig's usual one (`profile.ts`): a body warp\n * (`body.ts`) that breathes, follows the head's turn and tilt a little and\n * turns on BodyAngleX/Y/Z, its legs planted; a head deformer hung from it\n * that rolls about the chin and breathes; each arm hung from it too, as an\n * upper arm and a forearm turning about the shoulder and the elbow\n * (`arms.ts`); one small warp grid per feature\n * (each eye, each brow, the nose, the mouth), translating and foreshortening\n * it by its own lead over the plate; and the plate, the hair and the blush\n * moved by per-vertex keyforms of their own — the plate as up to four\n * islands of one drawing: a head that slides, a neck that stays on the torso\n * and two ears that lag. Blink, gaze, brows, mouth, breath and\n * hair sway are part warps and bindings under those. The model also declares\n * the default expressions and the Nod, Shake and Tilt motions\n * (`animations.ts`).\n */\n\nimport {\n IKI_FORMAT_VERSION,\n StandardParameter as P,\n parseIkiModel,\n type IkiBinding,\n type IkiDeformer,\n type IkiMesh,\n type IkiModel,\n type IkiParameter,\n type IkiPart,\n type IkiPhysics,\n type IkiWarp,\n type IkiWarpDeformer,\n} from \"@ikijs/format\";\nimport { DEFAULT_MOTIONS, defaultExpressions } from \"./animations\";\nimport {\n ARM_RANGE,\n armDeformers,\n armGeometry,\n armParts,\n type ArmGeometry,\n type ArmRole,\n} from \"./arms\";\nimport {\n BODY_WARP_ID,\n buildBodyWarp,\n headOwnBreath,\n headOwnRoll,\n} from \"./body\";\nimport { checkHeadEdges, checkLayers, checkStrandEdges } from \"./checks\";\nimport { renderedLander, sideIrises, solveContext } from \"./context\";\nimport { buildHeadFrame, type HeadFrame } from \"./head\";\nimport { buildFaceMesh, type Region } from \"./face-mesh\";\nimport {\n bh,\n boxOfLayer,\n bw,\n cellsFor,\n cx,\n cy,\n gridMesh,\n roundTo,\n unionBoxes,\n type Box,\n type Cells,\n} from \"./layout\";\nimport {\n roleOfPart,\n roleSpec,\n ROLE_TABLE,\n type Family,\n type RoleSpec,\n} from \"./roles\";\nimport { bake, lattice, X_STOPS, Y_STOPS, type Lattice } from \"./grid\";\nimport {\n chinSlide,\n earField,\n familyField,\n hairFrontBends,\n neckField,\n type Field,\n type HairFrontGrid,\n type TurnModel,\n} from \"./fields\";\nimport {\n buildTurn,\n checkedKeys,\n checkedNumber,\n fitTurn,\n resolveTurnTargets,\n TURN_TARGET_KEYS,\n turnReport,\n type ResolvedTargets,\n type TurnFit,\n} from \"./solve\";\nimport {\n blinkFold,\n browBindings,\n browReach,\n gazeBindings,\n gazeReach,\n hairHangWeight,\n hairSway,\n lashFold,\n localWarp,\n motionReach,\n mouthForm,\n mouthOpenGrow,\n mouthWiden,\n SWAY_RANGE,\n tiltHang,\n type Reach,\n} from \"./drivers\";\nimport {\n AMPLITUDE,\n STYLE_KNOBS,\n resolveStyle,\n type ResolvedStyle,\n} from \"./profile\";\nimport { type GenerateOptions, type LayerInput } from \"./types\";\n\n/** Mesh cells per role. The plate's head island carries the chin's lead and\n * the jaw's narrowing; the hair only sways and hangs. */\nconst MESH_CELLS: Record<string, Cells> = {\n face: { px: 28, min: 4, max: 24 },\n // The front hair eases from riding the face to holding the outline.\n hair_front: { px: 32, min: 3, max: 24 },\n hair_back: { px: 56, min: 3, max: 18 },\n};\nconst NECK_CELLS: Cells = { px: 20, min: 3, max: 12 };\nconst FEATURE_MESH_CELLS: Cells = { px: 14, min: 2, max: 12 };\n\ntype GridFamily = \"eye_L\" | \"eye_R\" | \"brow_L\" | \"brow_R\" | \"nose\" | \"mouth\";\n\n/** Grid cells per feature: each only translates, foreshortens and tilts, so a\n * few cells carry it; they mostly hold the room its own motions need. */\nconst GRID_CELLS: Record<GridFamily, Cells> = {\n eye_L: { px: 24, min: 2, max: 8 },\n eye_R: { px: 24, min: 2, max: 8 },\n brow_L: { px: 32, min: 2, max: 6 },\n brow_R: { px: 32, min: 2, max: 6 },\n nose: { px: 16, min: 2, max: 8 },\n mouth: { px: 16, min: 2, max: 8 },\n};\nconst WARP_ID: Record<GridFamily, string> = {\n eye_L: \"eyeWarp_L\",\n eye_R: \"eyeWarp_R\",\n brow_L: \"browWarp_L\",\n brow_R: \"browWarp_R\",\n nose: \"noseWarp\",\n mouth: \"mouthWarp\",\n};\nconst isGridFamily = (f: Family): f is GridFamily => f in WARP_ID;\n/** An arm's spec: the `arm` family, whose roles `arms.ts` rigs. */\nconst isArm = (spec: RoleSpec): spec is RoleSpec & { role: ArmRole } =>\n spec.family === \"arm\";\nconst GRID_PAD = 6;\n\ntype Grids = Map<Family, { lattice: Lattice; keyforms: number[][] }>;\n\nexport function generateIkiFromLayerSet(\n layers: LayerInput[],\n canvas: { width: number; height: number },\n options: GenerateOptions = {},\n): IkiModel {\n checkLayers(layers, canvas);\n const byRole = new Map(layers.map((l) => [l.role, l]));\n const has = (role: string) => byRole.has(role);\n const box = (role: string) => boxOfLayer(byRole.get(role)!);\n const hasNose = has(\"nose\");\n const plateHalf = byRole.get(\"face\")!.cropW / 2;\n\n checkHeadEdges(options.headEdges, byRole);\n checkStrandEdges(\n options.strandEdges,\n sideIrises(byRole),\n has(\"hair_front\") ? box(\"hair_front\") : undefined,\n );\n checkedKeys(\"style\", options.style, STYLE_KNOBS);\n const style = resolveStyle(options.style, (name, v, lo, hi) =>\n checkedNumber(name, v, lo, hi),\n );\n\n // Without a nose there is no turn to fit: the face turns on the profile,\n // inside its own outline. Every turn option — the cues, the measured head,\n // its edges and strands — is then inert; the edges and strands are still\n // checked against the layers, and the cues' object for a misspelt field.\n checkedKeys(\"turnTargets\", options.turnTargets, TURN_TARGET_KEYS);\n const targets: ResolvedTargets = hasNose\n ? resolveTurnTargets(options.turnTargets, plateHalf)\n : { given: new Set() };\n const turnOptions: GenerateOptions = hasNose ? options : {};\n const frameOptions = {\n headHalfWidth: targets.headHalfWidth,\n headEdges:\n targets.headHalfWidth !== undefined ? options.headEdges : undefined,\n };\n const solveFrame = buildHeadFrame(layers, frameOptions);\n\n // --- the turn ---\n const ctx = solveContext(solveFrame, byRole, turnOptions, hasNose);\n const boxes: TurnModel[\"boxes\"] = Object.fromEntries(\n ([\"eye_L\", \"eye_R\", \"brow_L\", \"brow_R\"] as const)\n .filter(has)\n .map((r) => [r, box(r)]),\n );\n const landmarks: Pick<\n TurnModel,\n \"boxes\" | \"noseAt\" | \"noseTopY\" | \"mouthAt\" | \"hairTop\" | \"hairFrontGrid\"\n > = {\n boxes,\n noseAt: ctx.noseAt,\n noseTopY: ctx.noseBox?.y1,\n mouthAt: ctx.mouthAt,\n hairTop: has(\"hair_front\") ? box(\"hair_front\").y1 : solveFrame.face.y1,\n // The field reads the grid the mesh is built on (the rebuilt frame below\n // differs only in the jaw's cut, which the grid does not read).\n hairFrontGrid: has(\"hair_front\")\n ? hairFrontGrid(box(\"hair_front\"), solveFrame, boxes)\n : undefined,\n };\n const build = (q: Parameters<typeof buildTurn>[2]) =>\n buildTurn(solveFrame, landmarks, q);\n // Without a nose there are no targets, but the art's room still bounds\n // the profile's turn.\n const fit: TurnFit = fitTurn(ctx, targets, style, build);\n\n // The jaw's cut takes the chin's shade only as far as the solved turn\n // keeps it inside the neck, so the frame is rebuilt with the chin's slide;\n // the two differ only in the cut, which the solve does not read.\n const frame = buildHeadFrame(layers, {\n ...frameOptions,\n chinSlide: chinSlide(fit.model),\n });\n const turn: TurnModel = { ...fit.model, frame };\n\n // --- the body warp the head and the arms hang from ---\n // An arm implies a body (`checkLayers`); its side is read off the body's\n // axis, and its shoulder is a pivot the body warp's band A must hold.\n const arms = new Map<ArmRole, ArmGeometry>();\n for (const spec of ROLE_TABLE) {\n const layer = byRole.get(spec.role);\n if (layer === undefined || !isArm(spec)) continue;\n arms.set(spec.role, armGeometry(layer, cx(box(\"body\"))));\n }\n const bodyWarp = has(\"body\")\n ? buildBodyWarp({\n body: byRole.get(\"body\")!,\n chin: { x: frame.axisX, y: frame.chinY },\n hh: frame.hh,\n pivots: [...arms.values()].map((g) => g.shoulder),\n })\n : undefined;\n\n // --- parts, with the warps and bindings that are not the turn's ---\n const parts: IkiPart[] = [];\n const reach = new Map<string, Reach>();\n let regionOf: Region[] = [];\n let headStart = 0;\n for (const spec of ROLE_TABLE) {\n const layer = byRole.get(spec.role);\n if (layer === undefined) continue;\n if (isArm(spec)) {\n // Two parts cut from the one crop, each on its own deformer.\n parts.push(\n ...armParts(spec.role, layer, arms.get(spec.role)!, parts.length),\n );\n continue;\n }\n const built = buildPart(\n spec,\n boxOfLayer(layer),\n parts.length,\n frame,\n byRole,\n style,\n landmarks.hairFrontGrid,\n );\n if (built.region !== undefined) {\n regionOf = built.region;\n headStart = built.headStart;\n }\n reach.set(spec.role, built.reach);\n parts.push(built.part);\n }\n\n // --- the features' grids ---\n const grids: Grids = new Map();\n for (const family of Object.keys(WARP_ID) as GridFamily[]) {\n const members = parts.filter(\n (p) => roleSpec(roleOfPart(p.id)).family === family,\n );\n if (members.length === 0) continue;\n const area = unionBoxes(\n members.map((p) => {\n const r = reach.get(p.id)!;\n const b = box(p.id);\n return {\n x0: b.x0 - r.left - GRID_PAD,\n x1: b.x1 + r.right + GRID_PAD,\n y0: b.y0 - r.bottom - GRID_PAD,\n y1: b.y1 + r.top + GRID_PAD,\n };\n }),\n );\n const cells = GRID_CELLS[family];\n const l = lattice(area, cells.px, cells.min, cells.max);\n grids.set(family, {\n lattice: l,\n keyforms: bake(l, familyField(turn, family)),\n });\n }\n\n // --- the plate, the blush and the hair: their own turn keyforms ---\n for (const part of parts) {\n const family = roleSpec(roleOfPart(part.id)).family;\n if (isGridFamily(family)) {\n part.deformer = WARP_ID[family];\n continue;\n }\n if (family === \"body\") {\n // Its mesh is cut on the body warp's lattice lines (`bodyMesh`), and\n // the warp is its whole motion.\n part.deformer = BODY_WARP_ID;\n part.mesh = bodyWarp!.mesh;\n continue;\n }\n // `armParts` hung each arm part on its own deformer.\n if (family === \"arm\") continue;\n part.deformer = \"headDeformer\";\n if (part.mesh === undefined) continue;\n const own = familyField(turn, family);\n const fieldOf: (i: number) => Field =\n part.id === \"face\" ? plateFields(turn, regionOf, own) : () => own;\n part.warps = [\n ...turnWarps(part.mesh, box(part.id), fieldOf),\n ...(part.warps ?? []),\n ];\n }\n\n const parameters = declareParameters(new Set(byRole.keys()));\n const model: IkiModel = {\n version: IKI_FORMAT_VERSION,\n name: \"auto-rigged\",\n canvas: { width: canvas.width, height: canvas.height },\n parameters,\n parts,\n deformers: deformers(frame, grids, bodyWarp?.deformer, arms),\n ...(has(\"hair_front\") ? { physics: hairPhysics() } : {}),\n expressions: defaultExpressions(new Set(parameters.map((p) => p.id))),\n motions: DEFAULT_MOTIONS,\n };\n\n // Reported only for a model that validates.\n const valid = parseIkiModel(model);\n if (hasNose && options.onTurnSolved) {\n options.onTurnSolved(\n turnReport(\n ctx,\n fit,\n renderedLander(turn, parts, grids, new Map([[\"face\", headStart]])),\n ),\n );\n }\n return valid;\n}\n\n/** A part's own turn and nod keyforms off its vertices' fields — split into\n * AngleX and AngleY, which add as the fields do. */\nfunction turnWarps(\n mesh: IkiMesh,\n b: Box,\n fieldOf: (i: number) => Field,\n): IkiWarp[] {\n return [\n localWarp(P.AngleX, mesh, b, X_STOPS, ([x, y], v, i) =>\n v === 0 ? [0, 0] : [fieldOf(i)(x, y, v, 0)[0], 0],\n ),\n localWarp(P.AngleY, mesh, b, Y_STOPS, ([x, y], v, i) =>\n v === 0 ? [0, 0] : [0, fieldOf(i)(x, y, 0, v)[1]],\n ),\n ];\n}\n\n/** The plate's islands each on their own motion: the head on the plate's\n * field, the ears lagging it, the neck still but for the shade under the\n * chin. */\nfunction plateFields(\n turn: TurnModel,\n region: Region[],\n head: Field,\n): (i: number) => Field {\n const ear = earField(turn);\n const neck = neckField(turn);\n return (i) =>\n region[i] === \"ear\" ? ear : region[i] === \"neck\" ? neck : head;\n}\n\n// --- parts ----------------------------------------------------------------------\n\nfunction buildPart(\n spec: RoleSpec,\n b: Box,\n order: number,\n frame: HeadFrame,\n byRole: Map<string, LayerInput>,\n style: ResolvedStyle,\n frontGrid: HairFrontGrid | undefined,\n): { part: IkiPart; reach: Reach; region?: Region[]; headStart: number } {\n const box = (role: string) => boxOfLayer(byRole.get(role)!);\n const part: IkiPart = {\n id: spec.role,\n color: [1, 1, 1, 1],\n width: bw(b),\n height: bh(b),\n transform: { x: cx(b), y: cy(b) },\n order,\n };\n const pivot: [number, number] = [frame.axisX, frame.chinY];\n const warps: IkiWarp[] = [];\n const bindings: IkiBinding[] = [];\n let extra: [number, number] = [0, 0];\n let mesh: IkiMesh | undefined;\n let region: Region[] | undefined;\n let headStart = 0;\n if (spec.role === \"face\") {\n const px = Math.min(MESH_CELLS.face.px, (2 * frame.wMax) / 14);\n const fm = buildFaceMesh(frame, b, { ...MESH_CELLS.face, px }, NECK_CELLS);\n mesh = fm.mesh;\n region = fm.region;\n headStart = fm.headStart;\n } else if (spec.role === \"hair_front\") {\n mesh = columnMesh(b, frontGrid!);\n } else if (spec.family !== \"body\") {\n const cells = MESH_CELLS[spec.role] ?? FEATURE_MESH_CELLS;\n // No coarser than a fraction of the head, whatever its size.\n const px = Math.min(cells.px, meshScale(spec.role, frame));\n mesh = gridMesh(\n cellsFor(bw(b), px, cells.min, cells.max),\n cellsFor(bh(b), px, cells.min, cells.max),\n );\n }\n if (mesh !== undefined) part.mesh = mesh;\n const side = spec.role.endsWith(\"_L\") ? \"L\" : \"R\";\n const eyeOpen = side === \"L\" ? P.EyeOpenLeft : P.EyeOpenRight;\n const hh = frame.hh;\n switch (spec.role) {\n case \"face\":\n if (region?.some((r) => r === \"neck\")) {\n const isNeck = region.map((r) => r === \"neck\");\n // The neck stays on the shoulders through the roll, undoing the\n // head's own roll only, and rises with them on a breath (the head\n // rises less).\n warps.push(\n tiltHang(\n mesh!,\n b,\n pivot,\n (_y, i) => (isNeck[i] ? 1 : 0),\n headOwnRoll(byRole.has(\"body\")),\n ),\n localWarp(P.Breath, mesh!, b, [0, 1], (_p, v, i) =>\n v === 1 && isNeck[i]\n ? [0, (AMPLITUDE.breathBody - AMPLITUDE.breathHead) * hh]\n : [0, 0],\n ),\n );\n }\n break;\n case \"eye_L\":\n case \"eye_R\":\n warps.push(blinkFold(eyeOpen, mesh!, b, style.blink));\n break;\n case \"lash_lower_L\":\n case \"lash_lower_R\":\n warps.push(blinkFold(eyeOpen, mesh!, b, style.blink, box(`eye_${side}`)));\n break;\n case \"lash_L\":\n case \"lash_R\":\n warps.push(lashFold(eyeOpen, mesh!, b, box(`eye_${side}`), style.blink));\n break;\n case \"iris_L\":\n case \"iris_R\":\n case \"pupil_L\":\n case \"pupil_R\":\n case \"highlight_L\":\n case \"highlight_R\": {\n // A highlight is a reflection: it travels half as far.\n const share = spec.role.startsWith(\"highlight\") ? 0.5 : 1;\n const iris = byRole.get(`iris_${side}`);\n const irisW =\n iris !== undefined ? iris.cropW : 0.46 * bw(box(`eye_${side}`));\n bindings.push(...gazeBindings(irisW, share));\n extra = gazeReach(irisW, share);\n part.clip = { masks: [`eye_${side}`] };\n break;\n }\n case \"brow_L\":\n case \"brow_R\": {\n const r = browReach(hh);\n bindings.push(...browBindings(side, r));\n extra = [0.15 * bw(b), r + 0.15 * bw(b)];\n break;\n }\n case \"mouth\":\n warps.push(mouthForm(mesh!, b));\n if (byRole.has(\"mouth_open\")) {\n warps.push(mouthWiden(mesh!, b));\n // Two multiplying fades: the closed lips are gone by the time the\n // open drawing is half grown.\n bindings.push(\n { parameter: P.MouthOpen, channel: \"opacity\", from: 1, to: 0 },\n { parameter: P.MouthOpen, channel: \"opacity\", from: 1, to: 0 },\n );\n extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];\n } else {\n // One drawing only: stretch it open downward from its top lip, to\n // the profile's open height, and wider.\n const grow = Math.max(\n 0,\n (AMPLITUDE.mouthOpenHeight * bw(b)) / bh(b) - 1,\n );\n bindings.push(\n {\n parameter: P.MouthOpen,\n channel: \"scaleY\",\n from: 0,\n to: roundTo(grow, 0.01),\n },\n {\n parameter: P.MouthOpen,\n channel: \"scaleX\",\n from: 0,\n to: roundTo(AMPLITUDE.mouthOpenWidth - 1, 0.01),\n },\n {\n parameter: P.MouthOpen,\n channel: \"translateY\",\n from: 0,\n to: -roundTo((grow * bh(b)) / 2, 0.01),\n },\n );\n extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), grow * bh(b)];\n }\n break;\n case \"mouth_open\":\n warps.push(mouthForm(mesh!, b), mouthOpenGrow(mesh!, b));\n bindings.push({\n parameter: P.MouthOpen,\n channel: \"opacity\",\n from: 0,\n to: 1,\n });\n extra = [(AMPLITUDE.mouthOpenWidth - 1) * (bw(b) / 2), 0];\n break;\n case \"blush_L\":\n case \"blush_R\":\n bindings.push({\n parameter: P.Cheek,\n channel: \"opacity\",\n from: AMPLITUDE.blushRest,\n to: 1,\n });\n break;\n case \"hair_front\":\n case \"hair_back\":\n if (byRole.has(\"hair_front\")) {\n const amp = style.sway * AMPLITUDE.sway * hh;\n warps.push(\n hairSway(P.HairSwayX, mesh!, b, amp),\n hairSway(P.HairSwayZ, mesh!, b, amp),\n );\n }\n warps.push(tiltHang(mesh!, b, pivot, hairHangWeight(frame.chinY, b.y0)));\n break;\n }\n if (warps.length > 0) part.warps = warps;\n if (bindings.length > 0) part.bindings = bindings;\n return {\n part,\n reach: motionReach(part.warps, mesh, b, extra),\n region,\n headStart,\n };\n}\n\n/** The front hair's mesh grid over its box `b`: even cells no coarser than a\n * fraction of the head, plus columns where its follow bends, so the mesh\n * carries the bends exactly. */\nfunction hairFrontGrid(\n b: Box,\n frame: HeadFrame,\n boxes: TurnModel[\"boxes\"],\n): HairFrontGrid {\n const cells = MESH_CELLS.hair_front;\n const px = Math.min(cells.px, meshScale(\"hair_front\", frame));\n const cols = cellsFor(bw(b), px, cells.min, cells.max);\n const rows = cellsFor(bh(b), px, cells.min, cells.max);\n const { inner, left, right } = hairFrontBends(frame, boxes);\n const step = bw(b) / cols;\n const xs = Array.from({ length: cols + 1 }, (_, c) => b.x0 + c * step);\n for (const x of [\n frame.axisX - left,\n frame.axisX - inner,\n frame.axisX + inner,\n frame.axisX + right,\n ]) {\n if (x <= b.x0 + 0.25 || x >= b.x1 - 0.25) continue;\n const near = xs.findIndex((v) => Math.abs(v - x) < 0.3 * step);\n if (near > 0 && near < xs.length - 1) xs[near] = x;\n else if (near < 0) xs.push(x);\n }\n xs.sort((p, q) => p - q);\n const ys = Array.from(\n { length: rows + 1 },\n (_, r) => b.y1 - (bh(b) * r) / rows,\n );\n return { xs, ys };\n}\n\n/** A mesh over `b` on `grid`; row 0 on top, each cell split as `gridMesh`'s. */\nfunction columnMesh(b: Box, grid: HairFrontGrid): IkiMesh {\n const { xs } = grid;\n const rows = grid.ys.length - 1;\n const vertices: number[] = [];\n const uvs: number[] = [];\n for (let r = 0; r <= rows; r++) {\n for (const x of xs) {\n const u = (x - b.x0) / bw(b);\n vertices.push(roundTo(u - 0.5, 1e-5), roundTo(0.5 - r / rows, 1e-5));\n uvs.push(roundTo(u, 1e-5), roundTo(r / rows, 1e-5));\n }\n }\n const n = xs.length;\n const indices: number[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c + 1 < n; c++) {\n const tl = r * n + c;\n const bl = tl + n;\n indices.push(bl, bl + 1, tl, tl, bl + 1, tl + 1);\n }\n }\n return { vertices, uvs, indices };\n}\n\nfunction meshScale(role: string, frame: HeadFrame): number {\n switch (role) {\n case \"hair_front\":\n case \"hair_back\":\n // It only sways and hangs: smooth bends a coarse mesh carries.\n return Math.max(2, (frame.shellRight - frame.shellLeft) / 9);\n default:\n return Infinity;\n }\n}\n\n// --- deformers, parameters, physics ---------------------------------------------\n\nfunction deformers(\n frame: HeadFrame,\n grids: Grids,\n bodyWarp: IkiWarpDeformer | undefined,\n arms: Map<ArmRole, ArmGeometry>,\n): IkiDeformer[] {\n const out: IkiDeformer[] = [];\n if (bodyWarp !== undefined) out.push(bodyWarp);\n for (const [role, g] of arms) out.push(...armDeformers(role, g));\n // On a body, the head's roll and breath are its own, on top of what the\n // body warp already gives the chin (`headOwnRoll`, `headOwnBreath`).\n const hasBody = bodyWarp !== undefined;\n const roll = headOwnRoll(hasBody);\n out.push({\n id: \"headDeformer\",\n ...(hasBody ? { parent: BODY_WARP_ID } : {}),\n pivot: { x: roundTo(frame.axisX, 0.01), y: roundTo(frame.chinY, 0.01) },\n bindings: [\n // AngleZ is clockwise-positive (Live2D's); a rotation is CCW-positive.\n { parameter: P.AngleZ, channel: \"rotate\", from: roll, to: -roll },\n {\n parameter: P.Breath,\n channel: \"translateY\",\n from: 0,\n to: roundTo(headOwnBreath(hasBody) * frame.hh, 0.01),\n },\n ],\n });\n for (const [family, g] of grids) {\n out.push({\n kind: \"warp\",\n id: WARP_ID[family as GridFamily],\n parent: \"headDeformer\",\n grid: {\n cols: g.lattice.cols,\n rows: g.lattice.rows,\n points: g.lattice.points,\n },\n warp2d: {\n parameter: P.AngleX,\n parameterY: P.AngleY,\n valuesX: X_STOPS,\n valuesY: Y_STOPS,\n keyforms2d: g.keyforms.map((offsets) => ({ offsets })),\n },\n });\n }\n return out;\n}\n\n/** Two springs, one per head axis the hair lags (a rig has one input). Each\n * settles at a modest share of its range, so a held turn or tilt leaves the\n * hair only a little swung. */\nfunction hairPhysics(): IkiPhysics[] {\n return [\n {\n id: \"hairSway\",\n input: { parameter: P.AngleX, weight: 1 },\n output: { parameter: P.HairSwayX, scale: 5 },\n mass: 1,\n stiffness: 30,\n damping: 3,\n },\n {\n id: \"hairTilt\",\n input: { parameter: P.AngleZ, weight: 1 },\n output: { parameter: P.HairSwayZ, scale: 8 },\n mass: 1,\n stiffness: 25,\n damping: 2.5,\n },\n ];\n}\n\nfunction declareParameters(roles: Set<string>): IkiParameter[] {\n const out: IkiParameter[] = [];\n const add = (\n id: string,\n name: string,\n min: number,\n max: number,\n def: number,\n ) => out.push({ id, name, min, max, default: def });\n add(P.AngleX, \"Head Angle\", -30, 30, 0);\n add(P.AngleY, \"Head Angle Y\", -30, 30, 0);\n add(P.AngleZ, \"Head Angle Z\", -30, 30, 0);\n if (roles.has(\"body\")) {\n add(P.BodyAngleX, \"Body Angle X\", -10, 10, 0);\n add(P.BodyAngleY, \"Body Angle Y\", -10, 10, 0);\n add(P.BodyAngleZ, \"Body Angle Z\", -10, 10, 0);\n }\n const [armMin, armMax] = ARM_RANGE;\n if (roles.has(\"arm_L\")) {\n add(P.ArmLeft, \"Arm L\", armMin, armMax, 0);\n add(P.ElbowLeft, \"Elbow L\", armMin, armMax, 0);\n }\n if (roles.has(\"arm_R\")) {\n add(P.ArmRight, \"Arm R\", armMin, armMax, 0);\n add(P.ElbowRight, \"Elbow R\", armMin, armMax, 0);\n }\n add(P.EyeOpenLeft, \"Eye L\", 0, 1, 1);\n add(P.EyeOpenRight, \"Eye R\", 0, 1, 1);\n if ([...roles].some((r) => /^(iris|pupil|highlight)_/.test(r))) {\n add(P.EyeballX, \"Gaze X\", -1, 1, 0);\n add(P.EyeballY, \"Gaze Y\", -1, 1, 0);\n }\n add(P.MouthOpen, \"Mouth Open\", 0, 1, 0);\n add(P.MouthForm, \"Mouth Form\", -1, 1, 0);\n if (roles.has(\"brow_L\")) {\n add(P.BrowLeftY, \"Brow L Y\", -1, 1, 0);\n add(P.BrowLeftAngle, \"Brow L Angle\", -1, 1, 0);\n }\n if (roles.has(\"brow_R\")) {\n add(P.BrowRightY, \"Brow R Y\", -1, 1, 0);\n add(P.BrowRightAngle, \"Brow R Angle\", -1, 1, 0);\n }\n if (roles.has(\"blush_L\") || roles.has(\"blush_R\")) {\n add(P.Cheek, \"Cheek\", 0, 1, 0);\n }\n add(P.Breath, \"Breath\", 0, 1, 0);\n if (roles.has(\"hair_front\")) {\n add(P.HairSwayX, \"Hair Sway X\", -SWAY_RANGE, SWAY_RANGE, 0);\n add(P.HairSwayZ, \"Hair Sway Z\", -SWAY_RANGE, SWAY_RANGE, 0);\n }\n return out;\n}\n","/**\n * The expressions and motions an auto-rigged model declares, each with a\n * description a host (an LLM, say) picks it by.\n *\n * The values are our own, picked by eye on Bob and the long-haired character\n * (2026-10) from soft, medium and strong candidates. A term's\n * blend follows its parameter: EyeOpen multiplies, so the procedural blink\n * keeps running under it (at 0 the eyes stay shut); MouthOpenY overwrites,\n * and a host's lip-sync, written after the expression, wins; everything else\n * adds onto a parameter that rests at 0, clamped to its range. Only Shake\n * sets a fade; everything else plays with the format's\n * `DEFAULT_FADE_SECONDS`, capped at half a clip. No curve sets an\n * interpolation, so each is smooth.\n */\n\nimport {\n StandardParameter as P,\n type IkiExpression,\n type IkiExpressionParameter,\n type IkiMotionClip,\n} from \"@ikijs/format\";\n\n/** Both brows up (+) or down (−), in BrowY units. */\nfunction browsY(y: number): IkiExpressionParameter[] {\n return [\n { parameter: P.BrowLeftY, value: y, blend: \"add\" },\n { parameter: P.BrowRightY, value: y, blend: \"add\" },\n ];\n}\n\n/**\n * Both brows tilted as a mirror pair: + drops the inner ends (angry), − lifts\n * them (sad). Brow angles are raw per side and CCW-positive on screen, and the\n * character's left brow sits at +x, so its inner end is its screen-left end,\n * which a CCW turn drops; the right brow's inner end is its screen-right end,\n * which a CCW turn lifts. A mirror pair therefore takes opposite signs.\n */\nfunction browsTilt(innerDown: number): IkiExpressionParameter[] {\n return [\n { parameter: P.BrowLeftAngle, value: innerDown, blend: \"add\" },\n { parameter: P.BrowRightAngle, value: -innerDown, blend: \"add\" },\n ];\n}\n\nfunction cheek(value: number): IkiExpressionParameter {\n return { parameter: P.Cheek, value, blend: \"add\" };\n}\n\nconst BROWS = [P.BrowLeftY, P.BrowRightY, P.BrowLeftAngle, P.BrowRightAngle];\n\ninterface DefaultExpression extends IkiExpression {\n /** The parameters its look rests on: a model that declares none of them\n * could not show what the description promises, so it goes without. */\n needs?: string[];\n}\n\n// A model declares the brows, the gaze and Cheek only with the layers they\n// move, so `defaultExpressions` filters these terms, and leaves out an entry\n// whose look rests on a missing part: shy on the blush, angry and sad on the\n// brows. Every entry keeps a term on EyeOpen, MouthOpenY or MouthForm, which\n// the rig always declares, so a kept one is never emptied (`parseIkiModel`\n// would reject one that was).\nconst EXPRESSIONS: DefaultExpression[] = [\n {\n id: \"smile\",\n description:\n \"Smiling and pleased: warm, friendly, content. For greetings, thanks, agreement and gentle happiness.\",\n parameters: [\n { parameter: P.MouthForm, value: 1, blend: \"add\" },\n ...browsY(0.25),\n cheek(0.4),\n ],\n },\n {\n id: \"laugh\",\n description:\n \"Laughing, eyes shut and mouth open: delighted, amused. For jokes, playfulness and big joy.\",\n parameters: [\n { parameter: P.EyeOpenLeft, value: 0, blend: \"multiply\" },\n { parameter: P.EyeOpenRight, value: 0, blend: \"multiply\" },\n { parameter: P.MouthForm, value: 1, blend: \"add\" },\n { parameter: P.MouthOpen, value: 0.8, blend: \"overwrite\" },\n ...browsY(0.4),\n cheek(0.65),\n ],\n },\n {\n id: \"angry\",\n description:\n \"Angry or annoyed, frowning. For irritation, frustration, indignation or scolding.\",\n needs: BROWS,\n parameters: [\n ...browsY(-0.5),\n ...browsTilt(0.8),\n { parameter: P.MouthForm, value: -0.9, blend: \"add\" },\n ],\n },\n {\n id: \"sad\",\n description:\n \"Sad or disappointed, downcast. For sorrow, regret, apology or sympathy.\",\n needs: BROWS,\n parameters: [\n ...browsY(0.35),\n ...browsTilt(-0.8),\n { parameter: P.MouthForm, value: -0.8, blend: \"add\" },\n ],\n },\n {\n id: \"surprised\",\n description:\n \"Surprised, mouth dropped open: startled, amazed. For shock, sudden news or disbelief.\",\n parameters: [\n ...browsY(0.8),\n { parameter: P.MouthOpen, value: 0.9, blend: \"overwrite\" },\n ],\n },\n {\n id: \"shy\",\n description:\n \"Shy or embarrassed: bashful, flustered. For being praised, teased or caught off guard.\",\n needs: [P.Cheek],\n parameters: [\n cheek(1),\n // Gaze down.\n { parameter: P.EyeballY, value: -0.65, blend: \"add\" },\n { parameter: P.MouthForm, value: 0.4, blend: \"add\" },\n ...browsTilt(-0.25),\n ],\n },\n];\n\n/** The default expressions a model with the `declared` parameters can show,\n * each keeping only its terms on them, in table order. */\nexport function defaultExpressions(\n declared: ReadonlySet<string>,\n): IkiExpression[] {\n return EXPRESSIONS.filter(\n (e) => e.needs === undefined || e.needs.some((id) => declared.has(id)),\n ).map(({ needs: _needs, ...e }) => ({\n ...e,\n parameters: e.parameters.filter((t) => declared.has(t.parameter)),\n }));\n}\n\n/**\n * The head motions, one clip per group: a host plays (`Nod`, 0). AngleX,\n * AngleY and AngleZ are always declared, so these need no filter. AngleY −30\n * looks down and +30 up, so a nod dips negative; AngleZ + tilts the top of\n * the head toward the viewer's right. No `Idle` group, so the procedural idle\n * stays whole.\n */\nexport const DEFAULT_MOTIONS: Record<string, IkiMotionClip[]> = {\n Nod: [\n {\n description: \"Nods yes: agreement, acknowledgement, understanding.\",\n duration: 1,\n curves: [\n {\n parameter: P.AngleY,\n keys: [\n [0, 0],\n [0.3, -18],\n [0.6, 4],\n [0.8, -1],\n [1, 0],\n ],\n },\n ],\n },\n ],\n Shake: [\n {\n description: \"Shakes the head no: disagreement, refusal, disbelief.\",\n duration: 1.2,\n // The first swing peaks at 0.2 s, which the default fade would still\n // be damping.\n fadeIn: 0.15,\n curves: [\n {\n parameter: P.AngleX,\n keys: [\n [0, 0],\n [0.2, -18],\n [0.45, 18],\n [0.7, -16],\n [0.95, 10],\n [1.2, 0],\n ],\n },\n ],\n },\n ],\n Tilt: [\n {\n description:\n \"Tilts the head to one side and back: curiosity, puzzlement, a question.\",\n duration: 1.4,\n curves: [\n {\n parameter: P.AngleZ,\n keys: [\n [0, 0],\n [0.35, 20],\n [1, 20],\n [1.4, 0],\n ],\n },\n ],\n },\n ],\n};\n","/**\n * The arms. Each `arm_L` / `arm_R` layer is one drawing of the whole arm,\n * hanging, its shoulder at the top. It becomes two parts on two nested matrix\n * deformers hung from the body warp:\n * - the upper arm (the role's own id) on `armDeformer_X`, which turns about\n * the shoulder, the deltoid cap's centre;\n * - the forearm (`forearm_X`) on `forearmDeformer_X`, a child of the arm's,\n * which turns about the elbow.\n * The shoulder pivot rides an all-weight-1 cell of the body warp (`body.ts`),\n * so the arm breathes and turns with the chest rigidly, never sheared.\n *\n * Both parts are cut from the one crop: they share its box, transform and\n * texture rect, and their meshes meet on the seam, the elbow pivot's row. The\n * upper arm is the band above the seam. The forearm is the band below it plus\n * a half-disc fan above it, centred on the elbow pivot. Iki has no glue\n * between meshes, and two bands hinged at a seam open a wedge as wide as the\n * arm on a bend; the half-disc turns about its own centre, so it rotates into\n * itself and keeps the joint covered at any bend.\n *\n * Draw order: hair_back < body < arm_L, forearm_L, arm_R, forearm_R < face …\n * < hair_front. The forearm draws over the upper arm, so its cap hides the\n * seam.\n *\n * Signs: ParamArmX + raises the arm outward on either side and ParamElbowX +\n * turns the forearm the same way, both in degrees 1:1. A rotation is\n * CCW-positive, so an arm whose shoulder lies right of the body's axis (+x,\n * the character's left) turns CCW for +, and one at −x turns CW.\n */\n\nimport {\n StandardParameter as P,\n type IkiDeformerBinding,\n type IkiMatrixDeformer,\n type IkiMesh,\n type IkiPart,\n} from \"@ikijs/format\";\nimport { BODY_WARP_ID } from \"./body\";\nimport { bh, boxOfLayer, bw, cx, cy, roundTo } from \"./layout\";\nimport { LayerGeometryError, type LayerInput } from \"./types\";\n\ntype Point = { x: number; y: number };\n\nexport type ArmRole = \"arm_L\" | \"arm_R\";\n\n/** The elbow lies this share of the way from the shoulder's row down to the\n * arm's last painted row (an arm drawn with its hand). Our own value. */\nexport const ELBOW_AT = 0.42;\n/** The rows the upper arm's width is read on, as fractions of the crop's\n * height, top to bottom: under the deltoid cap, above the elbow. Our own\n * values. */\nconst CAP_ROWS = [0.1, 0.3] as const;\n/** The elbow cap's fan segments over its half-turn. Our own value. */\nexport const CAP_SEGMENTS = 12;\n/** ParamArmX and ParamElbowX, degrees: from a little across the body to\n * 150° out, 30° short of straight up. Our own values. */\nexport const ARM_RANGE = [-30, 150] as const;\n/** Each arm's shoulder and elbow parameters. */\nexport const ARM_PARAMS: Record<ArmRole, { arm: string; elbow: string }> = {\n arm_L: { arm: P.ArmLeft, elbow: P.ElbowLeft },\n arm_R: { arm: P.ArmRight, elbow: P.ElbowRight },\n};\n/** Each arm's forearm part id (the upper arm keeps the role's) and its two\n * deformer ids. */\nexport const ARM_IDS: Record<\n ArmRole,\n { forearm: string; armDeformer: string; forearmDeformer: string }\n> = {\n arm_L: {\n forearm: \"forearm_L\",\n armDeformer: \"armDeformer_L\",\n forearmDeformer: \"forearmDeformer_L\",\n },\n arm_R: {\n forearm: \"forearm_R\",\n armDeformer: \"armDeformer_R\",\n forearmDeformer: \"forearmDeformer_R\",\n },\n};\n\nexport interface ArmGeometry {\n /** The shoulder pivot, model space: the deltoid cap's centre. */\n shoulder: Point;\n /** r_u: the upper arm's half-width under the cap, px. */\n shoulderRadius: number;\n /** The elbow pivot, model space. Its y is the seam the two meshes meet on. */\n elbow: Point;\n /** The forearm's half-disc radius, px. */\n capRadius: number;\n /** +1 for a shoulder right of the body's axis (+ turns CCW), −1 left of it\n * (+ turns CW). */\n side: 1 | -1;\n}\n\n/**\n * The arm's pivots, read off the widest opaque run of each crop row\n * (`rowRuns`); a row without one, or a layer without runs, reads as the\n * crop:\n * - r_u is half the median width over the `CAP_ROWS` rows;\n * - the shoulder pivot lies r_u under the first painted row's centre, at the\n * run centre of the row it lands in;\n * - the elbow is the centre of the row `ELBOW_AT` of the way from there to\n * the last painted row, at its run centre;\n * - the cap radius is half the elbow's run + 1 px, kept inside the crop.\n * Pivots are on the 0.01 grid, as the written model is. `bodyAxisX` is the\n * body's axis, model x: the shoulder's side of it sets the sign. An arm too\n * short for its width to put the elbow under the shoulder would rig\n * inverted, so it throws `LayerGeometryError`.\n */\nexport function armGeometry(layer: LayerInput, bodyAxisX: number): ArmGeometry {\n const { bbox, canvasW, canvasH, rowRuns } = layer;\n const b = boxOfLayer(layer);\n // Crop row k's widest run, canvas columns [start, end).\n const span = (k: number): [number, number] => {\n const runs = rowRuns?.[k] ?? [];\n if (runs.length === 0) return [bbox.x, bbox.x + bbox.w];\n let [s, e] = [runs[0], runs[1]];\n for (let i = 2; i < runs.length; i += 2) {\n if (runs[i + 1] - runs[i] > e - s) [s, e] = [runs[i], runs[i + 1]];\n }\n return [s, e];\n };\n const centreX = (k: number) => {\n const [s, e] = span(k);\n return (s + e) / 2 - canvasW / 2;\n };\n // Model y of crop row k's centre; k may be fractional.\n const rowY = (k: number) => canvasH / 2 - (bbox.y + k + 0.5);\n\n const painted =\n rowRuns?.flatMap((runs, k) => (runs.length > 0 ? [k] : [])) ?? [];\n const first = painted[0] ?? 0;\n const last = painted.at(-1) ?? bbox.h - 1;\n\n const lo = Math.ceil(CAP_ROWS[0] * bbox.h);\n // At least one row, on a crop too short for the band to hold one.\n const hi = Math.max(lo, Math.floor(CAP_ROWS[1] * bbox.h));\n const widths: number[] = [];\n for (let k = lo; k <= hi; k++) {\n const [s, e] = span(k);\n widths.push(e - s);\n }\n widths.sort((p, q) => p - q);\n const ru = widths[widths.length >> 1] / 2;\n\n // The shoulder's row, fractional: r_u under the first painted row.\n const ks = first + ru;\n const shoulder = {\n x: roundTo(centreX(Math.round(ks)), 0.01),\n y: roundTo(rowY(ks), 0.01),\n };\n const ke = Math.round(ks + ELBOW_AT * (last - ks));\n if (ke <= ks) {\n throw new LayerGeometryError(\n `auto-rig: layer \"${layer.fileName}\": the arm is too short for its width to place a shoulder above an elbow (draw the arm hanging, shoulder at the top)`,\n );\n }\n const elbow = { x: roundTo(centreX(ke), 0.01), y: roundTo(rowY(ke), 0.01) };\n const [s, e] = span(ke);\n const capRadius = Math.min(\n (e - s) / 2 + 1,\n elbow.x - b.x0,\n b.x1 - elbow.x,\n b.y1 - elbow.y,\n );\n return {\n shoulder,\n shoulderRadius: ru,\n elbow,\n capRadius,\n side: shoulder.x > bodyAxisX ? 1 : -1,\n };\n}\n\n/** A mesh from part-local ±0.5 vertices (a band's four corners, then any\n * fan's centre and arc), its UVs following them (u = x + 0.5,\n * v = 0.5 − y). */\nfunction meshOf(vertices: number[], indices: number[]): IkiMesh {\n const uvs = vertices.map((v, i) =>\n roundTo(i % 2 === 0 ? v + 0.5 : 0.5 - v, 1e-5),\n );\n return { vertices, uvs, indices };\n}\n\n/**\n * The arm's two parts over its crop's box: the upper arm, the band from the\n * crop's top to the seam, on `armDeformer_X` at `order`; the forearm, the\n * band from the seam to the crop's bottom plus the elbow cap, on\n * `forearmDeformer_X` at `order + 1`. The cap is a fan of `CAP_SEGMENTS`\n * triangles from the elbow pivot over the half-disc above the seam. Their\n * texture rect is the host's, as every part's is: both take the crop's\n * (`partIdsOfRole`).\n */\nexport function armParts(\n role: ArmRole,\n layer: LayerInput,\n g: ArmGeometry,\n order: number,\n): [IkiPart, IkiPart] {\n const b = boxOfLayer(layer);\n const lx = (x: number) => roundTo((x - cx(b)) / bw(b), 1e-5);\n const ly = (y: number) => roundTo((y - cy(b)) / bh(b), 1e-5);\n const seam = ly(g.elbow.y);\n // A full-width band from `top` down to `bottom`, split as `gridMesh`\n // splits a cell.\n const band = (top: number, bottom: number) => [\n -0.5,\n top,\n 0.5,\n top,\n -0.5,\n bottom,\n 0.5,\n bottom,\n ];\n const quad = [2, 3, 0, 0, 3, 1];\n\n const cap = [lx(g.elbow.x), seam];\n const fan: number[] = [];\n for (let i = 0; i <= CAP_SEGMENTS; i++) {\n const a = (Math.PI * i) / CAP_SEGMENTS;\n cap.push(\n lx(g.elbow.x + g.capRadius * Math.cos(a)),\n ly(g.elbow.y + g.capRadius * Math.sin(a)),\n );\n // The centre is vertex 4, after the band's four.\n if (i > 0) fan.push(4, 4 + i, 5 + i);\n }\n\n const part = (\n id: string,\n deformer: string,\n at: number,\n mesh: IkiMesh,\n ): IkiPart => ({\n id,\n color: [1, 1, 1, 1],\n width: bw(b),\n height: bh(b),\n transform: { x: cx(b), y: cy(b) },\n order: at,\n deformer,\n mesh,\n });\n const ids = ARM_IDS[role];\n return [\n part(role, ids.armDeformer, order, meshOf(band(0.5, seam), quad)),\n part(\n ids.forearm,\n ids.forearmDeformer,\n order + 1,\n meshOf([...band(seam, -0.5), ...cap], [...quad, ...fan]),\n ),\n ];\n}\n\n/**\n * The arm's two matrix deformers: `armDeformer_X`, hung from the body warp\n * at the shoulder, and `forearmDeformer_X`, hung from it at the elbow. Each\n * turns on its parameter, declared over `ARM_RANGE`, by side × the value in\n * degrees.\n */\nexport function armDeformers(\n role: ArmRole,\n g: ArmGeometry,\n): [IkiMatrixDeformer, IkiMatrixDeformer] {\n const ids = ARM_IDS[role];\n const params = ARM_PARAMS[role];\n // A binding maps the parameter's range onto [from, to]: these give\n // side · value, so 0 rests.\n const rotate = (parameter: string): IkiDeformerBinding => ({\n parameter,\n channel: \"rotate\",\n from: g.side * ARM_RANGE[0],\n to: g.side * ARM_RANGE[1],\n });\n return [\n {\n id: ids.armDeformer,\n parent: BODY_WARP_ID,\n pivot: { ...g.shoulder },\n bindings: [rotate(params.arm)],\n },\n {\n id: ids.forearmDeformer,\n parent: ids.armDeformer,\n pivot: { ...g.elbow },\n bindings: [rotate(params.elbow)],\n },\n ];\n}\n","/**\n * The body warp: one root warp grid over the whole body. It turns the upper\n * body on BodyAngleX/Y/Z, follows the head's turn (AngleX) and tilt (AngleZ)\n * a little, and breathes, with everything under the hips planted. The head\n * and the shoulders hang from it as matrix deformers, each riding the cell\n * that holds its pivot rigidly (the engine's `warpRigidFrame`).\n *\n * Every warp offsets a lattice point by its row line's weight times one field\n * (the keyform table in `buildBodyWarp`). The row lines run in three bands,\n * top to bottom:\n * - band A, weight 1, from P (`BODY_GRID_PAD`) above the highest of the\n * body's top and the pivots down to `yFull`: CHEST_DROP under the chin, or\n * P above the lowest pivot if that is lower;\n * - the ramp, weight smoothstep(a, yFull, y), down to the hips' line a\n * (`hipLine`), weight 0, so the waist bends smoothly into the legs;\n * - one weight-0 cell from a to P under the lower of a and the body's bottom.\n * On a body too short for that, `yFull` is the midpoint of a and the lowest\n * pivot: both bands shrink to the gap between them, and a stays the zero line.\n *\n * Each pivot's cell is all weight 1. Every pivot lies strictly above `yFull`,\n * and the engine binds a point that sits on a row line into the cell below\n * that line, so the cell holding a pivot has its four corners in band A. The\n * cell then moves by one affine map, and a matrix child rides it rigidly: the\n * head and the shoulders turn with the upper body and are never sheared by\n * the ramp.\n *\n * Every line and pivot is on the 0.01 grid, as the written model is, so the\n * bands need the lowest pivot only 0.02 above the hips, room for `yFull`\n * between them; less is art the rig cannot build on (`LayerGeometryError`),\n * as is a ramp too short to carry the motion without folding (`refuseFold`).\n */\n\nimport {\n StandardParameter as P,\n type IkiGridWarp,\n type IkiMesh,\n type IkiWarpDeformer,\n} from \"@ikijs/format\";\nimport {\n bh,\n boxOfLayer,\n bw,\n cellsFor,\n cx,\n cy,\n DEG,\n roundTo,\n smoothstep,\n type Box,\n} from \"./layout\";\nimport { Z_STOPS } from \"./drivers\";\nimport { X_STOPS } from \"./grid\";\nimport { AMPLITUDE, BODY, ROLL_DEG } from \"./profile\";\nimport { LayerGeometryError, type LayerInput } from \"./types\";\n\ntype Point = { x: number; y: number };\n\nexport const BODY_WARP_ID = \"bodyWarp\";\n/** P: how far the lattice reaches past the body and every pivot, px. Our\n * own value. */\nexport const BODY_GRID_PAD = 6;\n/** Band A reaches this far under the chin, hh: the chest moves as one. Our\n * own value. */\nexport const CHEST_DROP = 0.8;\n/** The body crop's rows the leg split is looked for in, as fractions of its\n * height, top to bottom. Our own values. */\nconst HIP_BAND = [0.35, 0.75] as const;\n/** A run is a leg when it is at least this share of the crop's width. Our\n * own value. */\nconst LEG_MIN = 0.1;\n/** With no leg split and no cut, the hips lie this share of the body's\n * height under its top. Our own value. */\nexport const HIP_FRACTION = 0.5;\n/** The body mesh's rows are at most this tall, px. Our own value. */\nexport const BODY_MESH_PX = 48;\n/** BodyAngleX/Y/Z stops: each motion is linear either side of rest, so the\n * extremes and rest carry it exactly. */\nconst BODY_STOPS = [-10, 0, 10];\n/** At any pose, each body warp cell's corner triangle keeps at least this\n * share of its rest area. Our own value. */\nconst FOLD_MARGIN = 0.01;\n\n/**\n * The hips' line a, model y: the body warp's weight-0 line, which nothing\n * under moves. The first rule that applies:\n * 1. the leg split: the top edge of the first crop row in `HIP_BAND` holding\n * two or more runs (`rowRuns`) each at least `LEG_MIN` of the crop's\n * width;\n * 2. the cut: a crop reaching the canvas's last row (a waist-cut bust) is\n * planted at its bottom edge;\n * 3. `HIP_FRACTION` of the body's height under its top.\n */\nexport function hipLine(layer: LayerInput): number {\n const { bbox, canvasH, rowRuns } = layer;\n // Model y of the crop's top edge; crop row k's top edge is `top − k`.\n const top = canvasH / 2 - bbox.y;\n if (rowRuns !== undefined) {\n const legMin = LEG_MIN * bbox.w;\n const last = Math.floor(HIP_BAND[1] * bbox.h);\n for (let k = Math.ceil(HIP_BAND[0] * bbox.h); k <= last; k++) {\n const runs = rowRuns[k];\n let legs = 0;\n for (let i = 0; i < runs.length; i += 2) {\n if (runs[i + 1] - runs[i] >= legMin) legs++;\n }\n if (legs >= 2) return roundTo(top - k, 0.01);\n }\n }\n if (bbox.y + bbox.h === canvasH) return roundTo(top - bbox.h, 0.01);\n return roundTo(top - HIP_FRACTION * bbox.h, 0.01);\n}\n\nexport interface BodyLattice {\n /** Column lines, model x, left to right. */\n xs: number[];\n /** Row lines, model y, top to bottom. */\n ys: number[];\n /** Each row line's weight. */\n weights: number[];\n /** Band A's lowest line, model y. */\n yFull: number;\n}\n\n/**\n * The body warp's rest lattice: its row lines and their weights as the\n * header sets them out, its columns even over the body and every pivot, P to\n * spare. `chin` and `pivots` are the pivots of the matrix deformers that hang\n * from the warp, `anchor` the hips' line (`hipLine`), which comes through as\n * the zero-weight line unchanged.\n */\nexport function bodyLattice(\n body: LayerInput,\n chin: Point,\n hh: number,\n pivots: Point[],\n anchor: number,\n): BodyLattice {\n const b = boxOfLayer(body);\n // Lines are worked out in whole hundredths, the grid the model is written\n // on, so every gap is exact. Each value is snapped by the same `roundTo`\n // the written pivots go through: a bare Math.round(v·100) disagrees with\n // it on some x.xx5 inputs, which could put a written pivot on `yFull`.\n const g = (v: number) => Math.round(roundTo(v, 0.01) * 100);\n const pad = BODY_GRID_PAD * 100;\n const all = [chin, ...pivots];\n const a = g(anchor);\n const p = Math.min(...all.map((q) => g(q.y)));\n if (p - a < 2) {\n throw new LayerGeometryError(\n `auto-rig: layer \"${body.fileName}\": its hips (y ${anchor}) leave no row line strictly between them and the lowest of the head's and shoulders' pivots (y ${p / 100}), so the body warp cannot plant the legs below the pivots`,\n );\n }\n let full = Math.min(g(chin.y - CHEST_DROP * hh), p - pad);\n if (full - a < pad) {\n // A short body: the midpoint of the hips and the lowest pivot, a whole\n // hundredth clear of each.\n full = Math.min(Math.max(Math.round((a + p) / 2), a + 1), p - 1);\n }\n const top = Math.max(g(b.y1), ...all.map((q) => g(q.y))) + pad;\n const bottom = Math.min(a, g(b.y0)) - pad;\n\n // Lines `from` down to `to` in `cells` even rows, snapped to the grid, the\n // count lowered until the spacing is at least one hundredth: snapped, the\n // lines then still strictly decrease.\n const split = (from: number, to: number, cells: number): number[] => {\n const n = Math.max(1, Math.min(cells, from - to));\n const out = [from];\n for (let i = 1; i < n; i++) {\n out.push(Math.round(from - ((from - to) * i) / n));\n }\n out.push(to);\n return out;\n };\n const bandA = split(top, full, cellsFor((top - full) / 100, 96, 1, 8));\n const ramp = split(full, a, cellsFor((full - a) / 100, 96, 2, 8));\n const rows = [...bandA, ...ramp.slice(1, -1)];\n const ys = [...rows.map((y) => y / 100), anchor, bottom / 100];\n const weights = [...rows.map((y) => smoothstep(a, full, y)), 0, 0];\n\n const x0 = Math.min(b.x0, ...all.map((q) => q.x)) - BODY_GRID_PAD;\n const x1 = Math.max(b.x1, ...all.map((q) => q.x)) + BODY_GRID_PAD;\n const cols = cellsFor(x1 - x0, 96, 2, 8);\n const xs: number[] = [];\n for (let c = 0; c <= cols; c++) {\n xs.push(roundTo(x0 + ((x1 - x0) * c) / cols, 0.01));\n }\n return { xs, ys, weights, yFull: full / 100 };\n}\n\n/**\n * The body part's mesh, in its ±0.5 space, row 0 on top. The engine moves\n * mesh vertices and a triangle interpolates between them, so a triangle\n * across the hips' line would drag the pixels under it along: the mesh's row\n * lines are every lattice row line inside the box (`rows`, top to bottom;\n * the hips' line and `yFull` among them) plus the box's top and bottom, each\n * gap split evenly into rows at most BODY_MESH_PX tall. Every field is linear\n * in x, so the columns are even.\n */\nexport function bodyMesh(b: Box, rows: number[]): IkiMesh {\n const lines = [b.y1, ...rows.filter((y) => y > b.y0 && y < b.y1), b.y0];\n const ys = [lines[0]];\n for (let i = 1; i < lines.length; i++) {\n const [from, to] = [lines[i - 1], lines[i]];\n const n = Math.ceil((from - to) / BODY_MESH_PX);\n for (let k = 1; k < n; k++) ys.push(from - ((from - to) * k) / n);\n ys.push(to);\n }\n const cols = cellsFor(bw(b), BODY_MESH_PX, 2, 16);\n const vertices: number[] = [];\n const uvs: number[] = [];\n for (const y of ys) {\n const vy = roundTo((y - cy(b)) / bh(b), 1e-5);\n for (let c = 0; c <= cols; c++) {\n const vx = roundTo(c / cols - 0.5, 1e-5);\n vertices.push(vx, vy);\n uvs.push(roundTo(vx + 0.5, 1e-5), roundTo(0.5 - vy, 1e-5));\n }\n }\n const indices: number[] = [];\n for (let r = 0; r + 1 < ys.length; r++) {\n for (let c = 0; c < cols; c++) {\n const tl = r * (cols + 1) + c;\n const tr = tl + 1;\n const bl = tl + cols + 1;\n const br = bl + 1;\n indices.push(bl, br, tl, tl, br, tr);\n }\n }\n return { vertices, uvs, indices };\n}\n\n/**\n * The root body warp and the body part's mesh on its lattice. Its `warps`,\n * in this order, each offset lattice point p = (x, y) by its line's weight w\n * times (at the + extreme; − mirrors the shift and the angle, the narrowing\n * holds):\n * - BodyAngleX ±10: x by bodySlide·hh − bodyNarrow·(x − cx(body));\n * - BodyAngleY ±10: y by bodyBow·hh (+ rises, − bows);\n * - BodyAngleZ ±10: the rotation about H = (cx(body), a) by −bodyRoll;\n * - AngleX ±30 (the follow): BodyAngleX's field at bodyFollowX of it;\n * - AngleZ ±30 (the follow): the rotation about H by −β, β = `followRoll`;\n * - Breath 1: y by breath·hh (the shoulders' breath).\n * BodyAngleZ and AngleZ are clockwise-positive (Live2D's) and a rotation is\n * CCW-positive, hence the minus. Rest keyforms are zero, and offsets are\n * rounded to 0.01 px, which keeps the roll the engine reads back off a cell\n * within 0.02° of its design value.\n */\nexport function buildBodyWarp({\n body,\n chin,\n hh,\n pivots,\n}: {\n body: LayerInput;\n chin: Point;\n hh: number;\n pivots: Point[];\n}): { deformer: IkiWarpDeformer; mesh: IkiMesh } {\n const b = boxOfLayer(body);\n const anchor = hipLine(body);\n const { xs, ys, weights } = bodyLattice(body, chin, hh, pivots, anchor);\n const hx = cx(b);\n // The upper body's field at the extreme's share t (−1, 0 or 1).\n const turn = (x: number, t: number) =>\n t * BODY.slide * hh - Math.abs(t) * BODY.narrow * (x - hx);\n const roll = (x: number, y: number, deg: number): [number, number] => {\n const c = Math.cos(deg * DEG) - 1;\n const s = Math.sin(deg * DEG);\n const [dx, dy] = [x - hx, y - anchor];\n return [c * dx - s * dy, s * dx + c * dy];\n };\n const warp = (\n parameter: string,\n values: number[],\n field: (x: number, y: number, t: number) => [number, number],\n ): IkiGridWarp => {\n const extreme = Math.max(...values.map(Math.abs));\n return {\n parameter,\n keyforms: values.map((value) => ({\n value,\n offsets: ys.flatMap((y, r) =>\n xs.flatMap((x) => {\n const [dx, dy] = field(x, y, value / extreme);\n return [\n roundTo(weights[r] * dx, 0.01),\n roundTo(weights[r] * dy, 0.01),\n ];\n }),\n ),\n })),\n };\n };\n const deformer: IkiWarpDeformer = {\n kind: \"warp\",\n id: BODY_WARP_ID,\n grid: {\n cols: xs.length - 1,\n rows: ys.length - 1,\n points: ys.flatMap((y) => xs.flatMap((x) => [x, y])),\n },\n warps: [\n warp(P.BodyAngleX, BODY_STOPS, (x, _y, t) => [turn(x, t), 0]),\n warp(P.BodyAngleY, BODY_STOPS, (_x, _y, t) => [0, t * BODY.bow * hh]),\n warp(P.BodyAngleZ, BODY_STOPS, (x, y, t) =>\n roll(x, y, -t * BODY.rollDeg),\n ),\n warp(P.AngleX, X_STOPS, (x, _y, t) => [BODY.followX * turn(x, t), 0]),\n warp(P.AngleZ, Z_STOPS, (x, y, t) => roll(x, y, -t * BODY.followRoll)),\n warp(P.Breath, [0, 1], (_x, _y, t) => [0, t * AMPLITUDE.breathBody * hh]),\n ],\n };\n refuseFold(body, deformer, anchor, [chin, ...pivots]);\n return { deformer, mesh: bodyMesh(b, ys) };\n}\n\n/**\n * Refuses a body its own motion would fold (`LayerGeometryError`). At every\n * pose each lattice cell must stay a convex quad turned as at rest: the\n * triangle at each of its corners, that corner and its two neighbours, keeps\n * FOLD_MARGIN of its rest area. The cell's bilinear map then folds nowhere,\n * and no body mesh triangle turns over, even one across a column line: every\n * field is affine in x along a row line (up to the 0.01 rounding), so the\n * band between two row lines is one bilinear map.\n *\n * The warps sum, so each combination of the six warps' stops is a pose to\n * check, 3⁵ · 2 of them. Between stops each warp moves linearly, which makes\n * a triangle's doubled area quadratic in each warp's share t of the span it\n * is in: it lies C·t(1 − t) under the stops' blend, C the cross product of\n * that span's moves of the triangle's two edges. Each warp's largest C / 4\n * comes off the least area at the stops.\n */\nfunction refuseFold(\n body: LayerInput,\n d: IkiWarpDeformer,\n anchor: number,\n pivots: Point[],\n): void {\n const { cols, rows, points } = d.grid;\n const warps = d.warps ?? [];\n const stride = cols + 1;\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tl = r * stride + c;\n const [tr, bl, br] = [tl + 1, tl + stride, tl + stride + 1];\n // Each corner, then its two neighbours counter-clockwise (y up).\n const corners = [\n [bl, br, tl],\n [br, tr, bl],\n [tr, tl, br],\n [tl, bl, tr],\n ];\n for (const [p, q, s] of corners) {\n const fold = leastArea(points, warps, p, q, s);\n if (fold.least >= FOLD_MARGIN * fold.rest) continue;\n const lowest = roundTo(Math.min(...pivots.map((v) => v.y)), 0.01);\n const pose = warps\n .map((w, i) => `${w.parameter} ${w.keyforms[fold.stops[i]].value}`)\n .join(\", \");\n throw new LayerGeometryError(\n `auto-rig: layer \"${body.fileName}\": the body is too short between its hips (y ${anchor}) and the lowest of the head's and shoulders' pivots (y ${lowest}) for its motion: its body warp's cell from x ${points[tl * 2]} to ${points[tr * 2]}, y ${points[tl * 2 + 1]} to ${points[bl * 2 + 1]}, would fold at or near ${pose}`,\n );\n }\n }\n }\n}\n\n/**\n * The doubled signed area of the triangle on lattice points p, q, s at rest,\n * the least it comes to at any pose (`refuseFold`), and each warp's stop\n * index at the combination of stops it is least at.\n */\nfunction leastArea(\n points: number[],\n warps: IkiGridWarp[],\n p: number,\n q: number,\n s: number,\n): { rest: number; least: number; stops: number[] } {\n // Each warp's moves of the edges p→q and p→s at each of its stops.\n const moves = warps.map((w) =>\n w.keyforms.map(({ offsets: o }) => [\n o[q * 2] - o[p * 2],\n o[q * 2 + 1] - o[p * 2 + 1],\n o[s * 2] - o[p * 2],\n o[s * 2 + 1] - o[p * 2 + 1],\n ]),\n );\n const cross = (e: number[]) => e[0] * e[3] - e[1] * e[2];\n const edges = [\n points[q * 2] - points[p * 2],\n points[q * 2 + 1] - points[p * 2 + 1],\n points[s * 2] - points[p * 2],\n points[s * 2 + 1] - points[p * 2 + 1],\n ];\n let least = Infinity;\n let stops: number[] = [];\n const at: number[] = [];\n const walk = (w: number, ax: number, ay: number, bx: number, by: number) => {\n if (w === moves.length) {\n const area = ax * by - ay * bx;\n if (area < least) [least, stops] = [area, [...at]];\n return;\n }\n moves[w].forEach(([mx, my, nx, ny], k) => {\n at[w] = k;\n walk(w + 1, ax + mx, ay + my, bx + nx, by + ny);\n });\n };\n walk(0, edges[0], edges[1], edges[2], edges[3]);\n for (const m of moves) {\n let most = 0;\n for (let k = 1; k < m.length; k++) {\n most = Math.max(most, cross(m[k].map((v, i) => v - m[k - 1][i])));\n }\n least -= most / 4;\n }\n return { rest: cross(edges), least, stops };\n}\n\n/**\n * The head's own roll at AngleZ ±30, degrees. Its world roll there is\n * `ROLL_DEG`. With a body, the head hangs from the body warp, whose follow\n * rolls the chin's cell by exactly β = `BODY.followRoll` at that extreme (the\n * cell is all weight 1, so it moves as a pure rotation), so the head's own\n * roll is ROLL_DEG − β and the two sum to ROLL_DEG. Under BodyAngleZ alone\n * the head's own roll is 0 and its world roll is the body's. Without a body,\n * β = 0.\n */\nexport function headOwnRoll(hasBody: boolean): number {\n return hasBody ? ROLL_DEG - BODY.followRoll : ROLL_DEG;\n}\n\n/**\n * The head's own breath at Breath 1, hh. The chin's net lift is\n * `breathHead`. With a body, the body warp already lifts the chin's cell\n * (all weight 1) by `breathBody`, so the head's own is\n * breathHead − breathBody, a slight drop. The neck island's\n * (breathBody − breathHead), relative to the head, then lands it at\n * breathBody, with the shoulders. Without a body, it is `breathHead`.\n */\nexport function headOwnBreath(hasBody: boolean): number {\n return hasBody\n ? AMPLITUDE.breathHead - AMPLITUDE.breathBody\n : AMPLITUDE.breathHead;\n}\n","import type { IkiMesh } from \"@ikijs/format\";\nimport type { LayerInput } from \"./types\";\n\n/** An axis-aligned box in model space (origin canvas centre, +y up). */\nexport interface Box {\n x0: number;\n x1: number;\n /** Bottom edge (smaller y). */\n y0: number;\n /** Top edge (larger y). */\n y1: number;\n}\n\nexport function boxOfLayer(layer: LayerInput): Box {\n return boxOfPixels(layer.bbox, layer.canvasW, layer.canvasH);\n}\n\nexport function boxOfPixels(\n b: { x: number; y: number; w: number; h: number },\n canvasW: number,\n canvasH: number,\n): Box {\n return {\n x0: b.x - canvasW / 2,\n x1: b.x + b.w - canvasW / 2,\n y0: canvasH / 2 - (b.y + b.h),\n y1: canvasH / 2 - b.y,\n };\n}\n\nexport const cx = (b: Box): number => (b.x0 + b.x1) / 2;\nexport const cy = (b: Box): number => (b.y0 + b.y1) / 2;\nexport const bw = (b: Box): number => b.x1 - b.x0;\nexport const bh = (b: Box): number => b.y1 - b.y0;\n\nexport function unionBoxes(boxes: Box[]): Box {\n return {\n x0: Math.min(...boxes.map((b) => b.x0)),\n x1: Math.max(...boxes.map((b) => b.x1)),\n y0: Math.min(...boxes.map((b) => b.y0)),\n y1: Math.max(...boxes.map((b) => b.y1)),\n };\n}\n\nexport const clamp = (v: number, lo: number, hi: number): number =>\n v < lo ? lo : v > hi ? hi : v;\n\nexport function smoothstep(e0: number, e1: number, v: number): number {\n if (e1 === e0) return v < e0 ? 0 : 1;\n const t = clamp((v - e0) / (e1 - e0), 0, 1);\n return t * t * (3 - 2 * t);\n}\n\nexport const DEG = Math.PI / 180;\n\n/** Round for the written model: every number the rig emits goes through one\n * of these, so the file stays small and a re-rig is byte-stable. */\nexport const roundTo = (v: number, step: number): number => {\n const r = Math.round(v / step) * step;\n // Normalise -0 and float noise from the multiply (0.30000000000000004).\n return r === 0\n ? 0\n : Number(r.toFixed(Math.max(0, -Math.floor(Math.log10(step)))));\n};\n\n/** How finely a mesh or grid is cut: about `px` per cell, `min`…`max` cells\n * a side. */\nexport interface Cells {\n /** Target cell size, px. */\n px: number;\n min: number;\n max: number;\n}\n\n/** Cells for a span of `size` px at about `cell` px each. */\nexport function cellsFor(\n size: number,\n cell: number,\n min: number,\n max: number,\n): number {\n return clamp(Math.ceil(size / cell), min, max);\n}\n\n/**\n * A regular grid mesh in part-local ±0.5 space, row 0 on top — the layout of\n * `createGridMesh`, with vertex coordinates rounded so the file stays small.\n */\nexport function gridMesh(cols: number, rows: number): IkiMesh {\n const vertices: number[] = [];\n const uvs: number[] = [];\n for (let r = 0; r <= rows; r++) {\n for (let c = 0; c <= cols; c++) {\n vertices.push(\n roundTo(c / cols - 0.5, 1e-5),\n roundTo(0.5 - r / rows, 1e-5),\n );\n uvs.push(roundTo(c / cols, 1e-5), roundTo(r / rows, 1e-5));\n }\n }\n const indices: number[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const tl = r * (cols + 1) + c;\n const tr = tl + 1;\n const bl = tl + cols + 1;\n const br = bl + 1;\n indices.push(bl, br, tl, tl, br, tr);\n }\n }\n return { vertices, uvs, indices };\n}\n\n/** Model-space position of each mesh vertex of a part laid over `box`. */\nexport function meshPoints(mesh: IkiMesh, box: Box): [number, number][] {\n const out: [number, number][] = [];\n for (let i = 0; i < mesh.vertices.length; i += 2) {\n out.push([\n cx(box) + mesh.vertices[i] * bw(box),\n cy(box) + mesh.vertices[i + 1] * bh(box),\n ]);\n }\n return out;\n}\n","/**\n * Everything a part does besides the head turn: the blink fold, gaze, brows,\n * mouth, hair sway, and the hang of hair and the neck's stillness under a\n * roll. Each is a per-vertex warp in the part's own ±0.5 space or a binding,\n * applied before the part's turn grid, so the turn carries it. Amplitudes are\n * the profile's (`profile.ts`).\n */\n\nimport {\n StandardParameter as P,\n type IkiBinding,\n type IkiMesh,\n type IkiWarp,\n} from \"@ikijs/format\";\nimport {\n bh,\n bw,\n cx,\n DEG,\n meshPoints,\n roundTo,\n smoothstep,\n type Box,\n} from \"./layout\";\nimport { AMPLITUDE, ROLL_DEG } from \"./profile\";\n\n/** Hair sway parameters' range: a physics output, in degrees of swing. */\nexport const SWAY_RANGE = 20;\n/** The sway grows down the layer as (distance from its top)^SWAY_CURVE. */\nconst SWAY_CURVE = 1.4;\n/** The share of a roll the long hair gives back by hanging. */\nconst HAIR_HANG = 0.35;\n/** Roll stops for the hang and the neck: the profile's roll (`ROLL_DEG`),\n * which the linear blend between 0 and ±30 carries within about a pixel. */\nexport const Z_STOPS = [-30, 0, 30];\n\ntype Vec = [number, number];\n\n/** A warp whose keyform at each value is the model-space displacement `f`\n * gives each vertex (`i` its index), stored in the part's local units. */\nexport function localWarp(\n parameter: string,\n mesh: IkiMesh,\n box: Box,\n values: number[],\n f: (p: Vec, value: number, i: number) => Vec,\n): IkiWarp {\n const pts = meshPoints(mesh, box);\n const w = bw(box);\n const h = bh(box);\n return {\n parameter,\n keyforms: values.map((value) => ({\n value,\n offsets: pts.flatMap((p, i) => {\n const [dx, dy] = f(p, value, i);\n return [roundTo(dx / w, 1e-4), roundTo(dy / h, 1e-4)];\n }),\n })),\n };\n}\n\n/** The roll AngleZ `v` gives a head that rolls `deg` at ±30, radians,\n * CCW-positive (AngleZ is clockwise-positive, Live2D's). */\nexport const rollOf = (v: number, deg = ROLL_DEG): number =>\n (-v / 30) * deg * DEG;\n\n/** How far past its own box, per side, a part's vertices can travel under\n * its warps (each at its extremes, summed) and its translate bindings —\n * the margin its turn grid must cover, or the engine clamps it flat. */\nexport interface Reach {\n left: number;\n right: number;\n bottom: number;\n top: number;\n}\n\nexport function motionReach(\n warps: IkiWarp[] | undefined,\n mesh: IkiMesh | undefined,\n box: Box,\n extra: Vec = [0, 0],\n): Reach {\n const out: Reach = {\n left: extra[0],\n right: extra[0],\n bottom: extra[1],\n top: extra[1],\n };\n if (mesh === undefined) return out;\n const pts = meshPoints(mesh, box);\n for (const warp of warps ?? []) {\n let l = 0;\n let r = 0;\n let b = 0;\n let t = 0;\n for (const k of warp.keyforms) {\n pts.forEach(([x, y], i) => {\n const px = x + k.offsets[2 * i] * bw(box);\n const py = y + k.offsets[2 * i + 1] * bh(box);\n l = Math.max(l, box.x0 - px);\n r = Math.max(r, px - box.x1);\n b = Math.max(b, box.y0 - py);\n t = Math.max(t, py - box.y1);\n });\n }\n out.left += l;\n out.right += r;\n out.bottom += b;\n out.top += t;\n }\n return out;\n}\n\n// --- eyes ---------------------------------------------------------------------\n\n/** The eye white folds shut onto a crease, the upper lid coming `travel` of\n * the eye's height down; as its clip region closes, the iris is cut away\n * rather than squashed. Shut, it has no height at all: any band left open\n * shows a strip of iris under the lash. A lower lash (`box`, drawn over the\n * iris) folds onto the same crease of its `eye`, so it moves with the\n * white's rows and closes into the seam under the upper lash. */\nexport function blinkFold(\n param: string,\n mesh: IkiMesh,\n box: Box,\n travel: number,\n eye: Box = box,\n): IkiWarp {\n const yc = eye.y1 - travel * bh(eye);\n return localWarp(param, mesh, box, [0, 1], ([, y], v) =>\n v === 1 ? [0, 0] : [0, yc - y],\n );\n}\n\n/** The upper lash comes down onto the crease and flattens over the seam the\n * folded white leaves. A lash is drawn arched; shut, that arch would read\n * as a smile, so its middle comes down further than its ends. */\nexport function lashFold(\n param: string,\n mesh: IkiMesh,\n lash: Box,\n eye: Box,\n travel: number,\n): IkiWarp {\n const yc = eye.y1 - travel * bh(eye) - 0.04 * bh(eye);\n const c = cx(lash);\n const half = bw(lash) / 2;\n const sag = 0.3 * bh(lash);\n return localWarp(param, mesh, lash, [0, 1], ([x, y], v) => {\n if (v === 1) return [0, 0];\n const u = (x - c) / half;\n return [0, yc + (y - lash.y0) * 0.5 - sag * (1 - u * u) - y];\n });\n}\n\n/** Gaze: the iris (and pupil) travel within the white, a fraction of the\n * iris's own width; a highlight is a reflection and travels half as far. */\nexport function gazeBindings(irisW: number, share = 1): IkiBinding[] {\n const gx = AMPLITUDE.gazeX * irisW * share;\n const gy = AMPLITUDE.gazeY * irisW * share;\n return [\n {\n parameter: P.EyeballX,\n channel: \"translateX\",\n from: -round1(gx),\n to: round1(gx),\n },\n {\n parameter: P.EyeballY,\n channel: \"translateY\",\n from: -round1(gy),\n to: round1(gy),\n },\n ];\n}\n\nexport function gazeReach(irisW: number, share = 1): Vec {\n return [AMPLITUDE.gazeX * irisW * share, AMPLITUDE.gazeY * irisW * share];\n}\n\n// --- brows ----------------------------------------------------------------------\n\n/** How far a brow raises and lowers, px. */\nexport function browReach(hh: number): number {\n return AMPLITUDE.brow * hh;\n}\n\nexport function browBindings(side: \"L\" | \"R\", reach: number): IkiBinding[] {\n const y = side === \"L\" ? P.BrowLeftY : P.BrowRightY;\n const a = side === \"L\" ? P.BrowLeftAngle : P.BrowRightAngle;\n return [\n {\n parameter: y,\n channel: \"translateY\",\n from: -round1(reach),\n to: round1(reach),\n },\n { parameter: a, channel: \"rotate\", from: -BROW_TILT, to: BROW_TILT },\n ];\n}\nexport const BROW_TILT = 15;\n\n// --- mouth ----------------------------------------------------------------------\n\n/** Smile lifts the corners and widens the mouth a little; frown the reverse. */\nexport function mouthForm(mesh: IkiMesh, box: Box): IkiWarp {\n const a = 0.3 * bh(box);\n const c = cx(box);\n const half = bw(box) / 2;\n return localWarp(P.MouthForm, mesh, box, [-1, 0, 1], ([x], v) => {\n if (v === 0) return [0, 0];\n const u = (x - c) / half;\n const widen = v > 0 ? 0.05 : 0.03;\n return [v * widen * (x - c), v * a * (u * u - 0.3)];\n });\n}\n\n/** The open drawing grows out of the closed lips: shut, it is a line along\n * its own top lip; open, it is as wide as the profile's mouth gets. */\nexport function mouthOpenGrow(mesh: IkiMesh, box: Box): IkiWarp {\n const c = cx(box);\n return localWarp(P.MouthOpen, mesh, box, [0, 1], ([x, y], v) =>\n v === 1\n ? [(AMPLITUDE.mouthOpenWidth - 1) * (x - c), 0]\n : [0, box.y1 + (y - box.y1) * 0.2 - y],\n );\n}\n\n/** The closed lips widen as they open (and fade). */\nexport function mouthWiden(mesh: IkiMesh, box: Box): IkiWarp {\n const c = cx(box);\n return localWarp(P.MouthOpen, mesh, box, [0, 1], ([x], v) => [\n v * (AMPLITUDE.mouthOpenWidth - 1) * (x - c),\n 0,\n ]);\n}\n\n// --- hair -------------------------------------------------------------------------\n\n/** Root-pinned sway: the top of the layer stays, its ends swing `amp` px at\n * full sway. */\nexport function hairSway(\n param: string,\n mesh: IkiMesh,\n box: Box,\n amp: number,\n): IkiWarp {\n return localWarp(\n param,\n mesh,\n box,\n [-SWAY_RANGE, 0, SWAY_RANGE],\n ([, y], v) => {\n const t = Math.max(0, (box.y1 - y) / bh(box));\n return [(v / SWAY_RANGE) * amp * t ** SWAY_CURVE, 0];\n },\n );\n}\n\n/**\n * Hang under a roll: the head rotates `deg` about `pivot` at AngleZ ±30;\n * each vertex is turned back by `weight(y, i)` of that. The head's world roll\n * is `ROLL_DEG`; on a body its own roll is that less the body's roll at the\n * chin (`headOwnRoll`). The neck undoes all of the head's own roll, so it\n * rides the torso; long hair undoes some of the world roll, so it hangs\n * rather than swinging out like a board.\n */\nexport function tiltHang(\n mesh: IkiMesh,\n box: Box,\n pivot: Vec,\n weight: (y: number, i: number) => number,\n deg = ROLL_DEG,\n): IkiWarp {\n return localWarp(P.AngleZ, mesh, box, Z_STOPS, ([x, y], v, i) => {\n const g = weight(y, i);\n if (g === 0 || v === 0) return [0, 0];\n const a = -g * rollOf(v, deg);\n const px = x - pivot[0];\n const py = y - pivot[1];\n return [\n pivot[0] + px * Math.cos(a) - py * Math.sin(a) - x,\n pivot[1] + px * Math.sin(a) + py * Math.cos(a) - y,\n ];\n });\n}\n\n/** Long hair's hang weight: none above the pivot, rising to HAIR_HANG at the\n * layer's bottom. */\nexport function hairHangWeight(\n pivotY: number,\n bottom: number,\n): (y: number) => number {\n // Hair that ends above the pivot (a fringe) hangs from nothing: it rolls\n // with the head.\n if (bottom >= pivotY) return () => 0;\n return (y) => HAIR_HANG * smoothstep(pivotY, bottom, y);\n}\n\nconst round1 = (v: number) => roundTo(v, 0.1);\n","/**\n * Warp grids: a family's rest lattice, its turn × nod keyforms, and the\n * landing of a point through them — the same bind-to-rest-cell, sample-the-\n * deformed-cell bilinear the engine renders with, so a cue measured here is\n * the cue the render shows.\n */\n\nimport type { Field } from \"./fields\";\nimport { cellsFor, clamp, roundTo, type Box } from \"./layout\";\n\n/** AngleX and AngleY stops: every motion is linear in each on either side of\n * rest, so the extremes and rest carry it exactly, and the bilinear blend\n * between them adds a turn and a nod. */\nexport const X_STOPS = [-30, 0, 30];\nexport const Y_STOPS = [-30, 0, 30];\n\nexport interface Lattice {\n box: Box;\n cols: number;\n rows: number;\n /** Rest points, row-major, row 0 on top. */\n points: number[];\n}\n\nexport function lattice(\n box: Box,\n cell: number,\n min: number,\n max: number,\n): Lattice {\n const cols = cellsFor(box.x1 - box.x0, cell, min, max);\n const rows = cellsFor(box.y1 - box.y0, cell, min, max);\n const points: number[] = [];\n for (let r = 0; r <= rows; r++) {\n const y = box.y1 - ((box.y1 - box.y0) * r) / rows;\n for (let c = 0; c <= cols; c++) {\n points.push(\n roundTo(box.x0 + ((box.x1 - box.x0) * c) / cols, 0.01),\n roundTo(y, 0.01),\n );\n }\n }\n return { box, cols, rows, points };\n}\n\n/** Keyforms for every (X_STOPS[i], Y_STOPS[j]) stop, filed at j·|X| + i. */\nexport function bake(l: Lattice, field: Field): number[][] {\n const out: number[][] = [];\n for (const ay of Y_STOPS) {\n for (const ax of X_STOPS) {\n const offsets: number[] = [];\n for (let k = 0; k < l.points.length; k += 2) {\n if (ax === 0 && ay === 0) {\n offsets.push(0, 0);\n continue;\n }\n const [dx, dy] = field(l.points[k], l.points[k + 1], ax, ay);\n offsets.push(roundTo(dx, 0.1), roundTo(dy, 0.1));\n }\n out.push(offsets);\n }\n }\n return out;\n}\n\n/** The offsets at (ax, AngleY 0): the engine's linear blend between the two\n * AngleX stops around it. */\nexport function keyformAt(keyforms: number[][], ax: number): number[] {\n const j = Y_STOPS.indexOf(0);\n const row = X_STOPS.map((_, i) => keyforms[j * X_STOPS.length + i]);\n return blendStops(X_STOPS, row, ax);\n}\n\n/** Linear blend of per-stop offset arrays at `v` (clamped to the stops). */\nexport function blendStops(\n values: number[],\n offsets: number[][],\n v: number,\n): number[] {\n const x = clamp(v, values[0], values[values.length - 1]);\n let i = 0;\n while (i < values.length - 2 && x > values[i + 1]) i++;\n const t = (x - values[i]) / (values[i + 1] - values[i]);\n return offsets[i].map((o, k) => o + (offsets[i + 1][k] - o) * t);\n}\n\n/** Where a rest point lands on the deformed grid (rest + offsets). */\nexport function land(\n l: Lattice,\n offsets: number[],\n x: number,\n y: number,\n): [number, number] {\n const { cols, rows, points } = l;\n const stride = cols + 1;\n let col = cols - 1;\n for (let c = 0; c < cols; c++) {\n if (x < points[(c + 1) * 2]) {\n col = c;\n break;\n }\n }\n let row = rows - 1;\n for (let r = 0; r < rows; r++) {\n if (y > points[(r + 1) * stride * 2 + 1]) {\n row = r;\n break;\n }\n }\n const x0 = points[col * 2];\n const x1 = points[(col + 1) * 2];\n const yT = points[row * stride * 2 + 1];\n const yB = points[(row + 1) * stride * 2 + 1];\n const s = clamp((x - x0) / (x1 - x0), 0, 1);\n const t = clamp((yT - y) / (yT - yB), 0, 1);\n const at = (r: number, c: number): [number, number] => {\n const k = (r * stride + c) * 2;\n return [points[k] + offsets[k], points[k + 1] + offsets[k + 1]];\n };\n const p00 = at(row, col);\n const p10 = at(row, col + 1);\n const p01 = at(row + 1, col);\n const p11 = at(row + 1, col + 1);\n const topX = p00[0] + (p10[0] - p00[0]) * s;\n const topY = p00[1] + (p10[1] - p00[1]) * s;\n const botX = p01[0] + (p11[0] - p01[0]) * s;\n const botY = p01[1] + (p11[1] - p01[1]) * s;\n return [topX + (botX - topX) * t, topY + (botY - topY) * t];\n}\n","/**\n * Input checks. A malformed layer is a host bug and throws a plain `Error`;\n * malformed turn options come from a caller and throw `TurnTargetError`, and\n * art the rig cannot build on (a body's hips, `body.ts`) throws\n * `LayerGeometryError`. `@ikijs/mcp` reports either as `{ ok: false }` rather\n * than a crash.\n */\n\nimport { boxOfLayer, cx, type Box } from \"./layout\";\nimport { checkArmsHaveBody, REQUIRED_ROLES, roleSpec } from \"./roles\";\nimport {\n TurnTargetError,\n type GenerateOptions,\n type HeadEdges,\n type LayerInput,\n} from \"./types\";\n\nconst finite = (v: unknown): v is number =>\n typeof v === \"number\" && Number.isFinite(v);\n\nconst isObject = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null;\n\n/** The face plate's mesh has at most 24 cells a side; at this size each is\n * still a pixel, so none collapses to nothing. */\nconst MIN_FACE_PX = 24;\n\nexport function checkLayers(\n layers: LayerInput[],\n canvas: { width: number; height: number },\n): void {\n if (!Array.isArray(layers) || layers.length === 0) {\n throw new Error(\n \"auto-rig: generateIkiFromLayerSet: layers must be a non-empty array\",\n );\n }\n if (!(finite(canvas?.width) && canvas.width > 0)) {\n throw new Error(\"auto-rig: canvas.width must be a positive number\");\n }\n if (!(finite(canvas?.height) && canvas.height > 0)) {\n throw new Error(\"auto-rig: canvas.height must be a positive number\");\n }\n const seen = new Set<string>();\n for (const l of layers) {\n roleSpec(l.role);\n if (seen.has(l.role)) {\n throw new Error(`auto-rig: role \"${l.role}\" appears twice`);\n }\n seen.add(l.role);\n const at = `auto-rig: layer \"${l.fileName}\"`;\n const { x, y, w, h } = l.bbox ?? {};\n if (\n ![x, y, w, h].every(finite) ||\n w <= 0 ||\n h <= 0 ||\n x < 0 ||\n y < 0 ||\n x + w > canvas.width ||\n y + h > canvas.height\n ) {\n throw new Error(\n `${at} has a bbox outside its ${canvas.width}x${canvas.height} canvas`,\n );\n }\n if (l.canvasW !== canvas.width || l.canvasH !== canvas.height) {\n throw new Error(\n `${at} was measured on a ${l.canvasW}x${l.canvasH} canvas, not ${canvas.width}x${canvas.height}`,\n );\n }\n // The crop the atlas holds is the bbox: the part is sized off one, the\n // plate's stand-in half-width off the other.\n if (l.cropW !== w || l.cropH !== h) {\n throw new Error(\n `${at}: crop ${l.cropW}x${l.cropH} is not its bbox ${w}x${h}`,\n );\n }\n if (l.role === \"face\" && (w < MIN_FACE_PX || h < MIN_FACE_PX)) {\n throw new Error(\n `${at}: the face is ${w}x${h} px; the face plate needs at least ${MIN_FACE_PX} px each way to be meshed`,\n );\n }\n if (l.rowHalfWidths !== undefined) {\n const rows = l.rowHalfWidths;\n if (!Array.isArray(rows) || rows.length !== h) {\n throw new Error(\n `${at}: rowHalfWidths must have one entry per crop row (${h})`,\n );\n }\n rows.forEach((v, i) => {\n if (!finite(v) || v < 0 || v > w / 2 + 0.5) {\n throw new Error(\n `${at}: rowHalfWidths[${i}] ${v} is not a half-width inside its crop`,\n );\n }\n });\n }\n if (l.rowRuns !== undefined) {\n const rows = l.rowRuns;\n if (!Array.isArray(rows) || rows.length !== h) {\n throw new Error(\n `${at}: rowRuns must have one entry per crop row (${h})`,\n );\n }\n rows.forEach((runs, i) => {\n if (\n !Array.isArray(runs) ||\n runs.length % 2 !== 0 ||\n !runs.every(\n (c, k) =>\n Number.isInteger(c) &&\n c >= x &&\n c <= x + w &&\n (k === 0 || c > runs[k - 1]),\n )\n ) {\n throw new Error(\n `${at}: rowRuns[${i}] ${JSON.stringify(runs)} is not an even-length, strictly increasing list of columns inside its crop (${x}..${x + w})`,\n );\n }\n });\n }\n if (l.jawRows !== undefined) {\n const cols = l.jawRows;\n if (!Array.isArray(cols) || cols.length !== w) {\n throw new Error(\n `${at}: jawRows must have one entry per crop column (${w})`,\n );\n }\n cols.forEach((v, i) => {\n if (!Number.isInteger(v) || (v !== -1 && (v < y || v >= y + h))) {\n throw new Error(\n `${at}: jawRows[${i}] ${v} is neither -1 nor a row of its crop`,\n );\n }\n });\n }\n if (l.denseCore !== undefined) {\n const c = l.denseCore;\n if (\n ![c.x, c.y, c.w, c.h].every(finite) ||\n c.w <= 0 ||\n c.h <= 0 ||\n c.x < x - 1 ||\n c.y < y - 1 ||\n c.x + c.w > x + w + 1 ||\n c.y + c.h > y + h + 1\n ) {\n throw new Error(`${at}: denseCore is not a box inside its crop`);\n }\n }\n }\n const missing = REQUIRED_ROLES.filter((r) => !seen.has(r));\n if (missing.length > 0) {\n throw new Error(`auto-rig: missing required role(s) ${missing.join(\", \")}`);\n }\n // `parseLayerRoles` refuses it too; a direct caller may not have run it.\n checkArmsHaveBody(seen);\n}\n\n/** Each entry names a layer of this set; the outermost left edge lies left\n * of the face, the outermost right edge right of it. */\nexport function checkHeadEdges(\n edges: HeadEdges | undefined,\n byRole: Map<string, LayerInput>,\n): void {\n if (edges === undefined) return;\n if (!isObject(edges))\n throw new TurnTargetError(\"headEdges must be an object\");\n for (const side of [\"left\", \"right\"] as const) {\n const list: unknown = edges[side];\n if (!Array.isArray(list)) {\n throw new TurnTargetError(`headEdges.${side} must be an array`);\n }\n list.forEach((e: unknown, i) => {\n if (!isObject(e) || typeof e.role !== \"string\" || !byRole.has(e.role)) {\n throw new TurnTargetError(\n `headEdges.${side}[${i}].role is not a layer in this set`,\n );\n }\n if (!finite(e.x)) {\n throw new TurnTargetError(\n `headEdges.${side}[${i}].x must be a finite number`,\n );\n }\n });\n }\n if (edges.left.length > 0 && edges.right.length > 0) {\n const axis = cx(boxOfLayer(byRole.get(\"face\")!));\n const left = Math.min(...edges.left.map((e) => e.x));\n const right = Math.max(...edges.right.map((e) => e.x));\n if (!(left < axis && axis < right)) {\n throw new TurnTargetError(\n `headEdges: the left edge ${left} and the right edge ${right} do not bracket the face (x ${axis})`,\n );\n }\n }\n}\n\n/** Strand edges describe the irises this set has, against bangs it has, on\n * a row both cover: each side's iris span inside its crop, outer edge\n * strictly outward; the run inside the bangs' crop, its outer end strictly\n * outward of the iris's centre and of its face-side end, and that end short\n * of the other iris's centre (a run reaching it is a fringe: `null`). */\nexport function checkStrandEdges(\n strand: GenerateOptions[\"strandEdges\"],\n irises: { left?: Box; right?: Box },\n hair: Box | undefined,\n): void {\n if (strand === undefined) return;\n if (!isObject(strand)) {\n throw new TurnTargetError(\"strandEdges must be an object\");\n }\n for (const side of [\"left\", \"right\"] as const) {\n const s: unknown = strand[side];\n if (s === undefined) continue;\n const at = `strandEdges.${side}`;\n if (!isObject(s)) throw new TurnTargetError(`${at} must be an object`);\n if (hair === undefined) {\n throw new TurnTargetError(\n `${at} names a bangs' run, but this layer set has no hair_front`,\n );\n }\n for (const k of [\"y\", \"irisOuter\", \"irisInner\", \"runOuter\"] as const) {\n if (!finite(s[k])) {\n throw new TurnTargetError(`${at}.${k} must be a finite number`);\n }\n }\n if (s.runFace !== null && !finite(s.runFace)) {\n throw new TurnTargetError(\n `${at}.runFace must be a finite number or null`,\n );\n }\n const iris = irises[side];\n const other = irises[side === \"left\" ? \"right\" : \"left\"];\n if (iris === undefined || other === undefined) {\n throw new TurnTargetError(\n `${at} names an iris this layer set does not have`,\n );\n }\n const y = s.y as number;\n const outer = s.irisOuter as number;\n const inner = s.irisInner as number;\n const runOuter = s.runOuter as number;\n const runFace = s.runFace as number | null;\n // Outward is −x on the left side, +x on the right.\n const sign = side === \"left\" ? -1 : 1;\n if (y < iris.y0 || y > iris.y1 || y < hair.y0 || y > hair.y1) {\n throw new TurnTargetError(\n `${at}.y ${y} is not on a row of both its iris and hair_front`,\n );\n }\n for (const [k, x] of [\n [\"irisOuter\", outer],\n [\"irisInner\", inner],\n ] as const) {\n if (x < iris.x0 || x > iris.x1) {\n throw new TurnTargetError(`${at}.${k} ${x} is off its iris's crop`);\n }\n }\n if (sign * (outer - inner) <= 0) {\n throw new TurnTargetError(\n `${at}.irisOuter ${outer} is not strictly outward of irisInner ${inner}`,\n );\n }\n for (const [k, x] of [\n [\"runOuter\", runOuter],\n [\"runFace\", runFace],\n ] as const) {\n if (x !== null && (x < hair.x0 || x > hair.x1)) {\n throw new TurnTargetError(`${at}.${k} ${x} is off hair_front's crop`);\n }\n }\n if (sign * (runOuter - cx(iris)) <= 0) {\n throw new TurnTargetError(\n `${at}.runOuter ${runOuter} is not strictly outward of its iris's centre`,\n );\n }\n if (runFace !== null && sign * (runOuter - runFace) <= 0) {\n throw new TurnTargetError(\n `${at}.runOuter ${runOuter} is not strictly outward of runFace ${runFace}`,\n );\n }\n if (runFace !== null && sign * (runFace - cx(other)) <= 0) {\n throw new TurnTargetError(\n `${at}.runFace ${runFace} reaches the other iris's centre; a run that does is a fringe, runFace null`,\n );\n }\n }\n}\n","/**\n * What the turn solve reads off the layers — the cue rows, the silhouette,\n * the landmarks — and the lander that reads a finished rig back the way the\n * engine renders it.\n */\n\nimport { StandardParameter as P, type IkiPart } from \"@ikijs/format\";\nimport type { HeadFrame } from \"./head\";\nimport {\n boxOfLayer,\n boxOfPixels,\n bw,\n cx,\n cy,\n meshPoints,\n unionBoxes,\n type Box,\n} from \"./layout\";\nimport { roleSpec, type Family } from \"./roles\";\nimport { blendStops, keyformAt, land, type Lattice } from \"./grid\";\nimport { familyField, type TurnModel } from \"./fields\";\nimport type { IrisRow, Lander, SolveContext } from \"./solve\";\nimport type { GenerateOptions, IrisStrand, LayerInput } from \"./types\";\n\ninterface SideBox {\n role: string;\n box: Box;\n}\n\n/** A pair of roles as they sit on the canvas, the −x one first — which is\n * the character's right by convention, but the art decides. */\nfunction sidePair(\n byRole: Map<string, LayerInput>,\n a: string,\n b: string,\n): { left: SideBox; right: SideBox } | undefined {\n const la = byRole.get(a);\n const lb = byRole.get(b);\n if (la === undefined || lb === undefined) return undefined;\n const [lo, hi] = [\n { role: a, box: boxOfLayer(la) },\n { role: b, box: boxOfLayer(lb) },\n ].sort((p, q) => cx(p.box) - cx(q.box));\n return { left: lo, right: hi };\n}\n\n/** The irises on each side of the face, by x. */\nexport function sideIrises(byRole: Map<string, LayerInput>): {\n left?: Box;\n right?: Box;\n} {\n const pair = sidePair(byRole, \"iris_L\", \"iris_R\");\n return pair === undefined\n ? {}\n : { left: pair.left.box, right: pair.right.box };\n}\n\nexport function solveContext(\n frame: HeadFrame,\n byRole: Map<string, LayerInput>,\n options: GenerateOptions,\n hasNose: boolean,\n): SolveContext {\n const box = (role: string) => boxOfLayer(byRole.get(role)!);\n // The cue rows: each iris's painted span on its centre row, as measured;\n // failing that its crop less the one-pixel alpha margin; failing irises,\n // the eye whites.\n const row = (\n s: SideBox,\n strand: IrisStrand | undefined,\n sideSign: -1 | 1,\n ): IrisRow => {\n if (strand !== undefined) {\n const lo = sideSign < 0 ? strand.irisOuter : strand.irisInner;\n const hi = sideSign < 0 ? strand.irisInner : strand.irisOuter;\n return { role: s.role, lo, hi, y: strand.y };\n }\n const inset = bw(s.box) > 4 ? 1 : 0;\n return {\n role: s.role,\n lo: s.box.x0 + inset,\n hi: s.box.x1 - inset,\n y: cy(s.box),\n };\n };\n const eyes = sidePair(byRole, \"eye_L\", \"eye_R\")!;\n const irises = sidePair(byRole, \"iris_L\", \"iris_R\");\n const pair = irises ?? eyes;\n const strand = irises ? options.strandEdges : undefined;\n const left = row(pair.left, strand?.left, -1);\n const right = row(pair.right, strand?.right, 1);\n\n // The silhouette at the eye row: the layers the measurer found there, each\n // landing through its own motion; without them, the held outline or the\n // plate's own painted edge.\n let candidates: SolveContext[\"candidates\"];\n const edges = options.headEdges;\n if (\n frame.hairShell &&\n edges &&\n edges.left.length > 0 &&\n edges.right.length > 0\n ) {\n candidates = {\n left: edges.left.map((e) => ({ role: e.role, x: e.x })),\n // A right edge names its outermost pixel column; the boundary is one on.\n right: edges.right.map((e) => ({ role: e.role, x: e.x + 1 })),\n };\n } else if (frame.hairShell) {\n candidates = {\n left: [{ role: \"hair_back\", x: frame.shellLeft }],\n right: [{ role: \"hair_back\", x: frame.shellRight }],\n };\n } else {\n const w = frame.paintedHalfAt(frame.eyeY);\n candidates = {\n left: [{ role: \"face\", x: frame.axisX - w }],\n right: [{ role: \"face\", x: frame.axisX + w }],\n };\n }\n const restHalf =\n (Math.max(...candidates.right.map((c) => c.x)) -\n Math.min(...candidates.left.map((c) => c.x))) /\n 2;\n\n const nose = byRole.get(\"nose\");\n let noseAt: { x: number; y: number } | undefined;\n let noseBox: Box | undefined;\n if (hasNose && nose !== undefined) {\n noseBox = nose.denseCore\n ? boxOfPixels(nose.denseCore, nose.canvasW, nose.canvasH)\n : boxOfLayer(nose);\n noseAt = { x: cx(noseBox), y: cy(noseBox) };\n }\n const mouthBox = byRole.has(\"mouth_open\")\n ? unionBoxes([box(\"mouth\"), box(\"mouth_open\")])\n : box(\"mouth\");\n const m = box(\"mouth\");\n return {\n frame,\n left,\n right,\n candidates,\n restHalf,\n strand,\n hasHairFront: byRole.has(\"hair_front\"),\n eyeBoxes: { left: eyes.left.box, right: eyes.right.box },\n noseAt,\n noseBox,\n mouthAt: { x: cx(m), y: cy(m) },\n mouthBox,\n };\n}\n\n/**\n * Lands a point the way the engine draws it: the part's mesh vertices go\n * through its baked grid at the stop (or take its own AngleX keyform), and\n * the point is read linearly off the mesh triangle it rests in — the GPU's\n * interpolation, not the field's. `from` names, per part, the first index of\n * the triangles a point may land on (the face's head island).\n */\nexport function renderedLander(\n turn: TurnModel,\n parts: IkiPart[],\n grids: Map<Family, { lattice: Lattice; keyforms: number[][] }>,\n from: Map<string, number> = new Map(),\n): Lander {\n const analytic = new Map<Family, ReturnType<typeof familyField>>();\n const landed = new Map<string, number[]>();\n const field = (role: string) => {\n const family = roleSpec(role).family;\n let f = analytic.get(family);\n if (f === undefined) analytic.set(family, (f = familyField(turn, family)));\n return f;\n };\n return (role, x, y, ax) => {\n const family = roleSpec(role).family;\n const part = parts.find((p) => p.id === role);\n const g = grids.get(family);\n const warp = part?.warps?.find((w) => w.parameter === P.AngleX);\n if (part === undefined || part.mesh === undefined || (!g && !warp)) {\n return x + field(role)(x, y, ax, 0)[0];\n }\n const box: Box = {\n x0: part.transform.x - part.width / 2,\n x1: part.transform.x + part.width / 2,\n y0: part.transform.y - part.height / 2,\n y1: part.transform.y + part.height / 2,\n };\n const rest = meshPoints(part.mesh, box);\n const key = `${role}@${ax}`;\n let xs = landed.get(key);\n if (xs === undefined) {\n if (g) {\n const offsets = keyformAt(g.keyforms, ax);\n xs = rest.map(([px, py]) => land(g.lattice, offsets, px, py)[0]);\n } else {\n const k = warp!.keyforms;\n const offsets = blendStops(\n k.map((kf) => kf.value),\n k.map((kf) => kf.offsets),\n ax,\n );\n xs = rest.map(([px], i) => px + offsets[2 * i] * bw(box));\n }\n landed.set(key, xs);\n }\n const idx = part.mesh.indices;\n for (let t = from.get(role) ?? 0; t < idx.length; t += 3) {\n const [a, b, c] = [idx[t], idx[t + 1], idx[t + 2]];\n const [ax0, ay0] = rest[a];\n const [bx0, by0] = rest[b];\n const [cx0, cy0] = rest[c];\n const d = (by0 - cy0) * (ax0 - cx0) + (cx0 - bx0) * (ay0 - cy0);\n if (Math.abs(d) < 1e-9) continue;\n const u = ((by0 - cy0) * (x - cx0) + (cx0 - bx0) * (y - cy0)) / d;\n const v = ((cy0 - ay0) * (x - cx0) + (ax0 - cx0) * (y - cy0)) / d;\n const w = 1 - u - v;\n if (u < -1e-6 || v < -1e-6 || w < -1e-6) continue;\n return u * xs[a] + v * xs[b] + w * xs[c];\n }\n // Off the mesh (between islands, or past a trimmed cell): the field.\n return x + field(role)(x, y, ax, 0)[0];\n };\n}\n","/**\n * The head's frame of reference, read off the layers: where its turn axis\n * runs, its eye row and chin (and so the profile's head unit), the face\n * plate's painted rows, the neck the face layer carries and the jaw line that\n * separates the two, and the silhouette the measured head draws.\n */\n\nimport { boxOfLayer, clamp, cx, cy, type Box } from \"./layout\";\nimport type { HeadEdges, LayerInput } from \"./types\";\n\nexport interface Neck {\n /** Where the jaw's outline meets the neck's sides, model y. */\n topY: number;\n /** The neck's half-width there. */\n half: number;\n /** The widest the neck gets below that (a flare into the collar). */\n span: number;\n /** Its narrowest, between the two: where its outline runs. */\n waist: number;\n /** Under a measured jaw stroke, given the chin's slide: how far from the\n * axis the cut draws the end of the chin's shade band (see JAW_SHADE). */\n bandEnd?: number;\n}\n\n/** Ears the face layer paints on the plate's sides: a band of rows where the\n * outline juts out past the head's own and back in. */\nexport interface Ears {\n /** The band's top and bottom rows, model y. */\n top: number;\n bottom: number;\n /** The head's own half-width on row `y` of the band, under the ear. */\n attachAt(y: number): number;\n /** The ears' widest half-width. */\n outer: number;\n}\n\nexport interface HeadFrame {\n canvasW: number;\n canvasH: number;\n face: Box;\n /** The head's vertical centre line, model x (the face plate's centre). */\n axisX: number;\n /** The eye row (the iris centres), model y. */\n eyeY: number;\n mouthY: number;\n /** The chin tip — the jaw outline's lowest point — model y. */\n chinY: number;\n /** The profile's head unit `hh`, px: the eye row → the chin tip. */\n hh: number;\n /** Half the face plate's painted width on row `y`. */\n paintedHalfAt(y: number): number;\n /** The face plate's widest half-width. */\n wMax: number;\n /** The head's own widest half-width, its ears left out. */\n headMax: number;\n /** Whether the face carried a measured row profile. */\n hasProfile: boolean;\n /** The neck the face layer carries below its jaw, if any. */\n neck?: Neck;\n /** The ears it paints on its sides, if any. */\n ears?: Ears;\n /** The head's lower boundary at column x, model y: just under the jaw's\n * outline across the neck, just under the plate's own edge elsewhere.\n * What lies below it (the neck) stays with the body. */\n cutAt(x: number): number;\n /** The rows the plate's width change is read at. */\n cheekY: number;\n jawY: number;\n /** The held silhouette's edges at the eye row, model x. */\n shellLeft: number;\n shellRight: number;\n /** True when a measured head (hair) is wider than the face plate. */\n hairShell: boolean;\n /** The head half-width the turn cues are fractions of. */\n holdBase: number;\n /** A hair layer's opaque runs on the pixel row holding model y, as model x\n * boundaries `[start0, end0, start1, end1, …]` (its `rowRuns`); `[]` off\n * its crop, `undefined` when the layer is absent or carries none. */\n hairRuns(role: \"hair_front\" | \"hair_back\", y: number): number[] | undefined;\n /** The face's runs on model row `y`, as `hairRuns` answers them. */\n faceRuns(y: number): number[] | undefined;\n}\n\n/** The outermost edge of `runs` (model x boundaries) on `side` of the axis:\n * the last run's end on +x, the first run's start on −x; `undefined` when\n * no run reaches past the axis on that side. */\nexport function outerEdge(\n runs: number[],\n axisX: number,\n side: -1 | 1,\n): number | undefined {\n if (runs.length === 0) return undefined;\n const x = side > 0 ? runs[runs.length - 1] : runs[0];\n return side * (x - axisX) > 0 ? x : undefined;\n}\n\n/** How far the run of `runs` holding the pixel just inside boundary `x` on\n * `side` reaches inward of `x` and outward past it, px; 0 both where that\n * pixel is transparent. A run beyond a gap does not count. */\nexport function runReach(\n runs: number[],\n x: number,\n side: -1 | 1,\n): { inward: number; outward: number } {\n // The pixel just inside x: [x − 1, x) on +x, [x, x + 1) on −x.\n const px = side > 0 ? x - 1 : x;\n for (let k = 0; k < runs.length; k += 2) {\n const [a, b] = [runs[k], runs[k + 1]];\n if (a <= px && px + 1 <= b) {\n return side > 0\n ? { inward: x - a, outward: b - x }\n : { inward: b - x, outward: x - a };\n }\n }\n return { inward: 0, outward: 0 };\n}\n\n/** Rows filled in; `null` without a usable profile. */\nfunction filledProfile(rows: number[] | undefined): number[] | null {\n if (rows === undefined || !rows.some((v) => v > 0)) return null;\n const out = rows.slice();\n const first = out.findIndex((v) => v > 0);\n for (let i = 0; i < first; i++) out[i] = out[first];\n for (let i = first + 1; i < out.length; i++)\n if (!(out[i] > 0)) out[i] = out[i - 1];\n return out;\n}\n\n/** A light box filter: a stray pixel on the outline must not move the cut. */\nconst smoothProfile = (rows: number[]): number[] =>\n boxSmooth(rows, Math.max(1, Math.round(rows.length * 0.01)));\n\n/** Where an ear juts out: the outline steps out by EAR_STEP of the plate's\n * widest half-width within EAR_ROWS rows, and back in below. */\nconst EAR_STEP = 0.03;\nconst EAR_ROWS = 3;\n\n/**\n * An ear on the plate's outline: a step out, a band at least a tenth of the\n * eye→chin span tall, and a step back in, all above the chin. The head's own\n * outline under it is the line between the rows just outside the band.\n */\nfunction findEars(\n raw: number[],\n wMax: number,\n firstRow: number,\n lastRow: number,\n minRows: number,\n maxRows: number,\n): { top: number; bottom: number } | undefined {\n const step = Math.max(4, EAR_STEP * wMax);\n for (let t = Math.max(firstRow, EAR_ROWS); t < lastRow; t++) {\n if (raw[t] - raw[t - EAR_ROWS] < step) continue;\n for (let b = t + minRows; b <= Math.min(lastRow, t + maxRows); b++) {\n if (raw[b - EAR_ROWS] - raw[b] >= step) {\n return { top: t - EAR_ROWS, bottom: b };\n }\n }\n return undefined;\n }\n return undefined;\n}\n\nfunction boxSmooth(v: number[], k: number): number[] {\n return v.map((_, i) => {\n let s = 0;\n let n = 0;\n for (let j = i - k; j <= i + k; j++) {\n if (j < 0 || j >= v.length) continue;\n s += v[j];\n n++;\n }\n return s / n;\n });\n}\n\n/** How far under the jaw's outline the cut runs, px: the stroke's\n * antialiased fringe stays on the head. */\nconst CUT_MARGIN = 2;\n/** The cut takes the lowest of each column's neighbours this many columns\n * either side, and is read linearly between columns. On a jaw rising away\n * from the chin, that draws the cut's shape — the shade band's end among it\n * — up to one column more than that further out. */\nconst CUT_LOW = 3;\n/** How much of a depth under the jaw's line holds at offset d from the axis:\n * all of it under the chin, thinning evenly to none at the neck's outline,\n * where the outline's own first pixels lie. The cut's fringe margin thins\n * so, and the depth the neck's hidden rows sample the drawing at. */\nexport function fadeToOutline(d: number, nk: Neck): number {\n return Math.max(0, 1 - d / nk.waist);\n}\n\n/** A measured stroke is the jaw's only if it runs within STROKE_SLACK px of\n * the median of the STROKE_RUN columns either side of it. */\nconst STROKE_RUN = 4;\nconst STROKE_SLACK = 6;\n/** Under a measured jaw stroke, the dark band a chin casts on the neck goes\n * with the chin too (hh): left on the neck, it reads as a second jaw line\n * once the chin slides off it. It goes only as far as a full turn keeps it\n * on the neck: given the chin's slide at AngleX 30, the cut draws the\n * band's end no nearer the waist than that slide and a CUT_MARGIN, so at\n * ±30 the end lands at least 2 px inside the neck's outline. Carried\n * further, a turn slides it past the outline, an unlined wedge of neck over\n * the outline's top. */\nconst JAW_SHADE = 0.05;\n\nexport function buildHeadFrame(\n layers: LayerInput[],\n opts: {\n headHalfWidth?: number;\n headEdges?: HeadEdges;\n /** The chin's slide at AngleX 30, px. Without it the chin's shade band\n * reaches the neck's outline. */\n chinSlide?: number;\n },\n): HeadFrame {\n const byRole = new Map(layers.map((l) => [l.role, l]));\n const faceLayer = byRole.get(\"face\")!;\n const { canvasW, canvasH } = faceLayer;\n const face = boxOfLayer(faceLayer);\n const axisX = cx(face);\n const plateHalf = faceLayer.cropW / 2;\n\n const centreY = (role: string) => {\n const l = byRole.get(role);\n return l === undefined ? undefined : cy(boxOfLayer(l));\n };\n const pair = (a: string, b: string) => {\n const ya = centreY(a);\n const yb = centreY(b);\n return ya === undefined || yb === undefined ? undefined : (ya + yb) / 2;\n };\n const eyeY = pair(\"iris_L\", \"iris_R\") ?? pair(\"eye_L\", \"eye_R\")!;\n const mouthY = centreY(\"mouth\")!;\n\n // Model y of crop row r's centre, and of its lower boundary.\n const rowY = (r: number) => canvasH / 2 - (faceLayer.bbox.y + r + 0.5);\n const raw = filledProfile(faceLayer.rowHalfWidths);\n const profile = raw === null ? null : smoothProfile(raw);\n\n let wMax = plateHalf;\n let paintedHalfAt: (y: number) => number = () => plateHalf;\n let neck: Neck | undefined;\n let ears: Ears | undefined;\n let headMax = plateHalf;\n let chinY = face.y0;\n let cutAt: (x: number) => number = () => face.y0 - 1;\n\n if (profile !== null && raw !== null) {\n wMax = Math.max(...profile);\n headMax = wMax;\n let widestRow = 0;\n for (let r = 0; r < profile.length; r++) {\n if (profile[r] >= wMax - 0.5) widestRow = r;\n }\n const prof = profile;\n paintedHalfAt = (y: number) => {\n const r = canvasH / 2 - y - faceLayer.bbox.y - 0.5;\n const i = clamp(Math.floor(r), 0, prof.length - 1);\n const j = Math.min(i + 1, prof.length - 1);\n const t = clamp(r - i, 0, 1);\n return prof[i] + (prof[j] - prof[i]) * t;\n };\n\n // Ears, looked for between the plate's top fifth and the chin: the\n // plate's profile with their band replaced by the head's own outline\n // under them (a line between the rows just outside the band).\n const rawRows = raw;\n const earless = (chin: number): number[] => {\n const rowOf = (y: number) =>\n Math.round(canvasH / 2 - y - faceLayer.bbox.y - 0.5);\n const span = Math.max(1, eyeY - chin);\n const found = findEars(\n rawRows,\n wMax,\n Math.round(0.2 * rawRows.length),\n Math.min(rawRows.length - 1, rowOf(chin)),\n Math.round(0.1 * span),\n Math.round(0.8 * span),\n );\n if (found === undefined) return profile;\n const { top, bottom } = found;\n const a = rawRows[top];\n const b = rawRows[bottom];\n const attach = (r: number) =>\n a + ((b - a) * (r - top)) / Math.max(1, bottom - top);\n let outer = 0;\n for (let r = top; r <= bottom; r++) outer = Math.max(outer, rawRows[r]);\n ears = {\n top: rowY(top) + 0.5,\n bottom: rowY(bottom) - 0.5,\n attachAt: (y: number) =>\n attach(clamp(canvasH / 2 - y - faceLayer.bbox.y - 0.5, top, bottom)),\n outer,\n };\n return smoothProfile(\n rawRows.map((v, r) => (r > top && r < bottom ? attach(r) : v)),\n );\n };\n\n // A neck: below the jaw the plate settles onto a narrow plateau that\n // runs on for a while (the last few rows are the neck's own cut edge).\n const n = profile.length;\n const tail = Math.max(1, Math.floor(n * 0.05));\n let minW = Infinity;\n for (let r = widestRow; r < n - tail; r++)\n minW = Math.min(minW, profile[r]);\n if (Number.isFinite(minW) && minW < 0.7 * wMax) {\n const threshold = minW + 0.15 * (wMax - minW);\n let neckRow = -1;\n for (let r = widestRow + 1; r < n; r++) {\n if (profile[r] <= threshold) {\n neckRow = r;\n break;\n }\n }\n if (neckRow >= 0 && n - neckRow >= 0.12 * n) {\n let span = 0;\n let waist = Infinity;\n for (let r = neckRow; r < n; r++) {\n span = Math.max(span, profile[r]);\n if (r < n - tail) waist = Math.min(waist, profile[r]);\n }\n neck = {\n topY: rowY(neckRow),\n half: profile[neckRow],\n span,\n waist: Math.min(waist, profile[neckRow]),\n };\n }\n }\n\n if (neck !== undefined) {\n const nk = neck;\n // Where the measurer found the jaw's stroke, per crop column: model y\n // of its lower boundary — only inside the neck, and only between the\n // neck's top and its bottom (a dark mark anywhere else is not a jaw).\n const jaw = faceLayer.jawRows;\n const rawStroke = (i: number): number | undefined => {\n const row = jaw?.[i];\n if (row === undefined || row < 0) return undefined;\n const y = canvasH / 2 - (row + 1);\n return y <= nk.topY + 2 && y > face.y0 + 0.1 * (nk.topY - face.y0)\n ? y\n : undefined;\n };\n // A jaw line runs on from column to column: a stroke far off its\n // neighbours' is some other mark the scan met (a collar, a choker, a\n // column that slipped through the line's antialiasing), not the jaw.\n const strokes = Array.from({ length: faceLayer.cropW }, (_, i) =>\n rawStroke(i),\n );\n const strokeAt = (i: number): number | undefined => {\n const y = strokes[i];\n if (y === undefined) return undefined;\n const near: number[] = [];\n for (let j = i - STROKE_RUN; j <= i + STROKE_RUN; j++) {\n const v = strokes[j];\n if (j !== i && v !== undefined) near.push(v);\n }\n if (near.length < STROKE_RUN) return undefined;\n near.sort((a, b) => a - b);\n const median = near[near.length >> 1];\n return Math.abs(y - median) <= STROKE_SLACK ? y : undefined;\n };\n const colX = (i: number) => faceLayer.bbox.x + i + 0.5 - canvasW / 2;\n // The chin: the stroke's lowest point near the axis, or failing a\n // measured stroke the anime proportion — about half the eye→mouth span\n // under the mouth — kept between the neck's top and its bottom.\n let measuredChin = Infinity;\n for (let i = 0; i < faceLayer.cropW; i++) {\n if (Math.abs(colX(i) - axisX) > 0.35 * nk.half) continue;\n const y = strokeAt(i);\n if (y !== undefined) measuredChin = Math.min(measuredChin, y);\n }\n chinY = Number.isFinite(measuredChin)\n ? measuredChin\n : clamp(\n mouthY - 0.55 * (eyeY - mouthY),\n face.y0 + 0.4 * (nk.topY - face.y0),\n nk.topY,\n );\n // The jaw's own outline at a column offset d from the axis, off the\n // neck: the lowest row above the neck whose span, less any ear, reaches\n // it.\n const neckRow = Math.round(\n canvasH / 2 - nk.topY - faceLayer.bbox.y - 0.5,\n );\n const head = earless(chinY);\n headMax = Math.max(...head);\n const outlineAt = (d: number): number => {\n for (let r = neckRow; r >= 0; r--) {\n if (head[r] >= d) return rowY(r) - 0.5;\n }\n // A column wholly outside the head (past its ears' reach, say)\n // collapses to its top.\n return face.y1;\n };\n const chin = chinY;\n const shade = JAW_SHADE * Math.max(1, eyeY - chin);\n // Where the band thins to nothing: CUT_LOW + 1 columns short of the\n // furthest the cut may draw its end. Without a slide, at the neck's\n // outline.\n const reach =\n opts.chinSlide === undefined\n ? nk.waist\n : clamp(\n nk.waist - opts.chinSlide - CUT_MARGIN - (CUT_LOW + 1),\n 0,\n nk.waist,\n );\n // The furthest column the band reaches under a measured stroke.\n let banded = -1;\n const cut = new Float64Array(faceLayer.cropW);\n for (let i = 0; i < faceLayer.cropW; i++) {\n const d = Math.abs(colX(i) - axisX);\n // Across the neck, the jaw's measured stroke; without one, a V from\n // where the jaw meets the neck's sides down to the chin. Beside the\n // neck, the jaw's own outline (below it the layer is empty, save a\n // collar flare the neck keeps).\n const stroke = d <= nk.half ? strokeAt(i) : undefined;\n // The chin's shade goes with the head only across the neck's middle,\n // thinning to nothing at its reach (see JAW_SHADE). The stroke's\n // fringe margin thins on to the outline itself, where not even that\n // goes: the outline's own first pixels would go with it.\n const band = reach > 0 ? Math.max(0, 1 - d / reach) : 0;\n if (stroke !== undefined && band > 0) banded = Math.max(banded, d);\n const y =\n stroke !== undefined\n ? stroke - shade * band - CUT_MARGIN * fadeToOutline(d, nk)\n : (d <= nk.half\n ? chin + (nk.topY - chin) * (d / Math.max(1, nk.half))\n : outlineAt(d)) - CUT_MARGIN;\n // A column wholly outside the head stays collapsed onto its top.\n cut[i] = y >= face.y1 ? face.y1 : y;\n }\n // The lowest of each column's neighbours: a stroke that dips between\n // two sampled columns stays on the head.\n const low = cut.map((_, i) => {\n let m = Infinity;\n for (let j = i - CUT_LOW; j <= i + CUT_LOW; j++) {\n if (j >= 0 && j < cut.length) m = Math.min(m, cut[j]);\n }\n return m;\n });\n // Where the cut draws the band's end: CUT_LOW columns past the last\n // it reaches, then read toward the next.\n if (opts.chinSlide !== undefined && banded >= 0)\n nk.bandEnd = banded + CUT_LOW + 1;\n cutAt = (x: number) => {\n const f = x - (faceLayer.bbox.x - canvasW / 2) - 0.5;\n const i = clamp(Math.floor(f), 0, low.length - 1);\n const j = Math.min(i + 1, low.length - 1);\n const t = clamp(f - i, 0, 1);\n return Math.max(face.y0, low[i] + (low[j] - low[i]) * t);\n };\n } else {\n // No neck: the plate is all head, save its ears, which it ends beside.\n const head = earless(chinY);\n headMax = Math.max(...head);\n if (ears !== undefined) {\n const bottomOf = (d: number): number => {\n for (let r = head.length - 1; r >= 0; r--) {\n if (head[r] >= d) return rowY(r) - 0.5;\n }\n return face.y1;\n };\n cutAt = (x: number) => {\n const y = bottomOf(Math.abs(x - axisX));\n return y >= face.y1 ? face.y1 : Math.max(face.y0, y - CUT_MARGIN);\n };\n }\n }\n }\n\n const hh = Math.max(1, eyeY - chinY);\n\n const headHalf = opts.headHalfWidth;\n const hairShell = headHalf !== undefined;\n let shellLeft = axisX - plateHalf;\n let shellRight = axisX + plateHalf;\n if (hairShell) {\n if (\n opts.headEdges &&\n opts.headEdges.left.length > 0 &&\n opts.headEdges.right.length > 0\n ) {\n shellLeft = Math.min(...opts.headEdges.left.map((e) => e.x));\n // A right edge names its outermost pixel column; its outer boundary is\n // one pixel further.\n shellRight = Math.max(...opts.headEdges.right.map((e) => e.x)) + 1;\n } else {\n shellLeft = axisX - headHalf;\n shellRight = axisX + headHalf;\n }\n }\n\n const runsOf = (\n role: \"face\" | \"hair_front\" | \"hair_back\",\n y: number,\n ): number[] | undefined => {\n const l = byRole.get(role);\n if (l?.rowRuns === undefined) return undefined;\n const runs = l.rowRuns[Math.floor(canvasH / 2 - y) - l.bbox.y];\n return runs === undefined ? [] : runs.map((c) => c - canvasW / 2);\n };\n const hairRuns = (role: \"hair_front\" | \"hair_back\", y: number) =>\n runsOf(role, y);\n const faceRuns = (y: number) => runsOf(\"face\", y);\n\n return {\n canvasW,\n canvasH,\n face,\n axisX,\n eyeY,\n mouthY,\n chinY,\n hh,\n paintedHalfAt,\n wMax,\n headMax,\n hasProfile: profile !== null,\n neck,\n ears,\n cutAt,\n cheekY: eyeY - 0.5 * (eyeY - chinY),\n jawY: eyeY - 0.8 * (eyeY - chinY),\n shellLeft,\n shellRight,\n hairShell,\n holdBase: headHalf ?? plateHalf,\n hairRuns,\n faceRuns,\n };\n}\n","/**\n * The head's motion as one displacement field per family, read off the\n * profile (`profile.ts`). A turn is parallax: the plate translates,\n * each feature leads it by its own amount (and the eyes foreshorten about\n * their own centres), the front hair rides it, the back hair drifts slightly\n * against it, and the neck under the jaw does not move. A nod is the same,\n * vertically. Every field is linear in each parameter on each side of rest,\n * so the keyforms at 0 and ±30 carry it exactly, and a turn and a nod add.\n */\n\nimport type { Family } from \"./roles\";\nimport { clamp, cx, cy, DEG, smoothstep, type Box } from \"./layout\";\nimport { outerEdge, runReach, type HeadFrame } from \"./head\";\nimport { NOD, TURN } from \"./profile\";\n\nexport type Field = (\n x: number,\n y: number,\n ax: number,\n ay: number,\n) => [number, number];\n\ntype Side = { far: number; near: number };\ntype Nod = { up: number; down: number };\n\n/** Everything the fields need, in px (turn amounts along the turn at ±30). */\nexport interface TurnModel {\n frame: HeadFrame;\n /** The plate's translation, and the chin's lead over it. */\n face: number;\n chinLead: number;\n /** The plate's width at full turn, eye/cheek rows and jaw. */\n widthUpper: number;\n widthJaw: number;\n eye: Side;\n /** Each eye's width at full turn (far, near). */\n eyeScale: Side;\n brow: Side;\n nose: number;\n mouth: number;\n mouthWidth: number;\n /** The mouth's and the nose's tilts, as a share of the profile's. */\n tilt: number;\n hairFront: number;\n /** The front hair over the far eye: at least as far as that eye's outer\n * corner goes, so the lock over it keeps it no deeper than drawn. */\n hairFar: number;\n /** The front hair's outer edge — the head's outline where it draws it. */\n hairOuter: number;\n hairBack: number;\n /** The hair layers' width at full turn, about the axis (the silhouette). */\n shellScale: number;\n /** The far ear's width at full turn, about its outer edge. */\n earFarScale: number;\n /** Landmarks: each eye white's and brow's box, the nose's landmark and\n * bridge top, the mouth drawings' centre. */\n boxes: Partial<Record<\"eye_L\" | \"eye_R\" | \"brow_L\" | \"brow_R\", Box>>;\n noseAt?: { x: number; y: number };\n noseTopY?: number;\n mouthAt: { x: number; y: number };\n /** The front hair's top edge, model y. */\n hairTop: number;\n /** The front hair's mesh grid. The render interpolates linearly between\n * its vertices, so its outer edge's ride is bounded per vertex row. */\n hairFrontGrid?: HairFrontGrid;\n}\n\n/** The front hair's mesh grid, model coords: its vertex columns left to\n * right (even columns plus those where its follow bends), and its vertex\n * rows top to bottom, evenly spaced. */\nexport interface HairFrontGrid {\n xs: number[];\n ys: number[];\n}\n\n/** The nose's tip swings to the far side about its bridge top by this much\n * at a full turn: it stands further proud than its bridge. */\nexport const NOSE_TILT_DEG = 6;\n\n/** Screen-down hh at ±30 → model dy (y up), px. */\nfunction nodDy(v: Nod, ay: number, hh: number): number {\n const up = Math.max(0, ay) / 30;\n const down = Math.max(0, -ay) / 30;\n return -(up * v.up + down * v.down) * hh;\n}\n\n/** Rotate (px, py) about (ox, oy) by `a` radians, CCW; the displacement. */\nfunction spin(\n x: number,\n y: number,\n ox: number,\n oy: number,\n a: number,\n): [number, number] {\n if (a === 0) return [0, 0];\n const px = x - ox;\n const py = y - oy;\n return [\n px * Math.cos(a) - py * Math.sin(a) - px,\n px * Math.sin(a) + py * Math.cos(a) - py,\n ];\n}\n\n/** The head's own plate: a translation, the chin leading it, its width as\n * the profile and the fit give it. */\nexport function faceField(m: TurnModel): Field {\n const f = m.frame;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const chin = smoothstep(f.mouthY, f.chinY, y);\n const width =\n m.widthUpper +\n (m.widthJaw - m.widthUpper) * smoothstep(f.cheekY, f.jawY, y);\n // Without hair the plate is the silhouette, and the silhouette's own\n // width change is its.\n const shell = f.hairShell ? 0 : m.shellScale - 1;\n const dx =\n s * a * (m.face + m.chinLead * chin) +\n a * (width - 1 + shell) * (x - f.axisX);\n const t = Math.min(\n 1,\n Math.max(0, (f.face.y1 - y) / Math.max(1, f.face.y1 - f.chinY)),\n );\n const v = {\n up: NOD.faceTop.up + (NOD.chin.up - NOD.faceTop.up) * t,\n down: NOD.faceTop.down + (NOD.chin.down - NOD.faceTop.down) * t,\n };\n return [dx, nodDy(v, ay, f.hh)];\n };\n}\n\n/**\n * The ears the plate paints: on the head, but behind the face, so they lag\n * its slide, and nod with it. The far one's outer edge lags most, and the\n * ear narrows about it (to `earFarScale` of its width at a full turn, where\n * the head leaves it room): its root follows the head further, sliding a\n * little under the cheek, but never further than the head moves on the line\n * under the ear — so where the head leaves less room, it narrows less — and\n * its tucked strip no further than the head over it, so it stays covered. The\n * turn solve keeps the head moving at least as far on that line as the\n * ear's outer edge (`farEarCovered`), so the ear never widens. The near\n * one's root — what lies inside the head's own outline, tucked under it —\n * moves as the head moves it there, and the ear eases evenly out to its own\n * lag at its widest reach: it widens a little rather than sliding out from\n * under the head, so its tucked strip never shows.\n */\nexport function earField(m: TurnModel): Field {\n const f = m.frame;\n const ears = f.ears;\n if (ears === undefined) return () => [0, 0];\n const face = faceField(m);\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const dy = face(x, y, 0, ay)[1];\n const d = Math.abs(x - f.axisX);\n const attach = ears.attachAt(y);\n const span = Math.max(1, ears.outer - attach);\n if (sideOf(m, x, s) === \"far\") {\n const rim = TURN.earFar * m.face;\n // How much further than the rim the root goes at a full turn: as far\n // as the ear's narrowing takes it, but no further than the head there\n // — and where the head moves less than the rim, not at all: the ear\n // never widens.\n const root = earRoot(m, face, y, s);\n const lead = Math.max(\n 0,\n Math.min((1 - m.earFarScale) * span, root - rim),\n );\n let along = rim + (lead * (ears.outer - d)) / span;\n // The tucked strip, inside that line, no further than the head over\n // it: the narrowing's slope can outrun a head narrowing less there\n // (and should the head not cover the rim, this still keeps it).\n if (d < attach) along = Math.min(along, s * face(x, y, 30 * s, 0)[0]);\n return [s * a * along, dy];\n }\n if (d <= attach) return [face(x, y, ax, 0)[0], dy];\n const root = face(f.axisX + Math.sign(x - f.axisX) * attach, y, ax, 0)[0];\n const rim = s * a * TURN.earNear * m.face;\n const t = Math.min(1, (d - attach) / span);\n return [root + (rim - root) * t, dy];\n };\n}\n\n/** The head's motion along a full turn toward s on the line under the ears\n * at model y (the plate's `face` field), px. */\nfunction earRoot(m: TurnModel, face: Field, y: number, s: number): number {\n const f = m.frame;\n return s * face(f.axisX + s * f.ears!.attachAt(y), y, 30 * s, 0)[0];\n}\n\n/**\n * Whether the head covers the far ear's slide: on every row of the ear\n * islands (the band and the 2 px they run past it either way), the head\n * moves at least as far along a full turn, either way, on the line under the\n * ear as the far ear's outer edge does (`TURN.earFar` of the plate's slide).\n * True without ear islands.\n */\nexport function farEarCovered(m: TurnModel): boolean {\n const ears = m.frame.ears;\n if (ears === undefined) return true;\n const face = faceField(m);\n const rim = TURN.earFar * m.face;\n const y0 = ears.bottom - 2;\n const y1 = ears.top + 2;\n const n = Math.max(1, Math.ceil(y1 - y0));\n for (let i = 0; i <= n; i++) {\n const y = y0 + ((y1 - y0) * i) / n;\n for (const s of [-1, 1]) if (earRoot(m, face, y, s) < rim) return false;\n }\n return true;\n}\n\n/** How far the chin slides at a full turn, px. */\nexport function chinSlide(m: TurnModel): number {\n const f = m.frame;\n return Math.abs(faceField(m)(f.axisX, f.chinY, 30, 0)[0]);\n}\n\n/** How far the shade under the chin may slide across the neck, as a share of\n * the neck's half-width: its outline stays put, and the drawing between them\n * keeps more than half its width. */\nconst NECK_SHADE_MAX = 0.45;\n/** How far down from the chin's cut the shade still slides whole, as a share\n * of the neck below it. */\nconst NECK_SHADE_FULL = 0.2;\n\n/**\n * The neck the plate paints: still, its outline and its base on the\n * shoulders — but the shade the chin casts on it slides sideways with the\n * chin, most under the chin and not at all at the base, across and not over\n * its outline. (A nod needs none: looking down, the chin covers the shade;\n * looking up, it uncovers more of it, in the hidden top's shade.)\n */\nexport function neckField(m: TurnModel): Field {\n const f = m.frame;\n const nk = f.neck;\n if (nk === undefined) return () => [0, 0];\n const face = faceField(m);\n const full = chinSlide(m);\n const share = Math.min(1, (NECK_SHADE_MAX * nk.waist) / Math.max(1e-6, full));\n // By row only: from a little under the chin up it slides whole, fading to\n // nothing at the neck's base — the jaw's V and the neck's rows under it\n // make narrow cells, which a weight changing across them would fold.\n const bottom = f.face.y0;\n const tip = f.cutAt(f.axisX);\n const top = tip - NECK_SHADE_FULL * (tip - bottom);\n return (x, y, ax) => {\n const wy = Math.min(\n 1,\n Math.max(0, (y - bottom) / Math.max(1, top - bottom)),\n );\n const wx = Math.max(0, 1 - Math.abs(x - f.axisX) / nk.waist);\n return [share * face(f.axisX, f.chinY, ax, 0)[0] * wx * wy, 0];\n };\n}\n\nfunction sideOf(m: TurnModel, x: number, s: number): \"far\" | \"near\" {\n return s * (x - m.frame.axisX) > 0 ? \"far\" : \"near\";\n}\n\nfunction eyeField(m: TurnModel, box: Box): Field {\n const xe = cx(box);\n const ye = cy(box);\n const hh = m.frame.hh;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const side = sideOf(m, xe, s);\n const dx = s * a * m.eye[side] + a * (m.eyeScale[side] - 1) * (x - xe);\n const up = Math.max(0, ay) / 30;\n const down = Math.max(0, -ay) / 30;\n const squash =\n up * (NOD.eyeHeight.up - 1) + down * (NOD.eyeHeight.down - 1);\n return [dx, nodDy(NOD.eye, ay, hh) + squash * (y - ye)];\n };\n}\n\nfunction browField(m: TurnModel, box: Box): Field {\n const xb = cx(box);\n return (_x, _y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n return [s * a * m.brow[sideOf(m, xb, s)], nodDy(NOD.brow, ay, m.frame.hh)];\n };\n}\n\nfunction noseField(m: TurnModel): Field {\n const at = m.noseAt!;\n const top = m.noseTopY ?? at.y;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n // The tip swings toward the far side: a CCW turn of a point below the\n // bridge top moves it toward +x.\n const [tx, ty] = spin(\n x,\n y,\n at.x,\n top,\n s * a * m.tilt * NOSE_TILT_DEG * DEG,\n );\n return [s * a * m.nose + tx, nodDy(NOD.nose, ay, m.frame.hh) + ty];\n };\n}\n\nfunction mouthField(m: TurnModel): Field {\n const c = m.mouthAt;\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n // Narrower about its centre, then the far corner up: a CCW turn lifts\n // the +x corner, which is the far one turning toward +x.\n const wx = c.x + (x - c.x) * (1 + a * (m.mouthWidth - 1));\n const [tx, ty] = spin(\n wx,\n y,\n c.x,\n c.y,\n s * a * m.tilt * TURN.mouthTiltDeg * DEG,\n );\n return [\n s * a * m.mouth + wx - x + tx,\n nodDy(NOD.mouth, ay, m.frame.hh) + ty,\n ];\n };\n}\n\nfunction hairField(m: TurnModel, shift: number, nod: Nod): Field {\n const f = m.frame;\n return (x, _y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n return [\n s * a * shift + a * (m.shellScale - 1) * (x - f.axisX),\n nodDy(nod, ay, f.hh),\n ];\n };\n}\n\n/**\n * Where the front hair's follow bends, as offsets from the axis: it rides the\n * face whole out to the eyes' outer corners (`inner`), then eases evenly to\n * the outline's own follow at the outline on each side (`left`, `right`) —\n * spread over all of that width, since on the far side the lock is squeezed\n * by as much as the face out-turns the outline. The hair's mesh has columns\n * here, so it carries the bends exactly.\n */\nexport function hairFrontBends(\n frame: HeadFrame,\n boxes: TurnModel[\"boxes\"],\n): { inner: number; left: number; right: number } {\n const f = frame;\n const eyes = [boxes.eye_L, boxes.eye_R].filter(\n (e): e is Box => e !== undefined,\n );\n const inner = Math.max(\n 1,\n Math.min(\n f.paintedHalfAt(f.eyeY),\n ...eyes.map((e) => Math.max(f.axisX - e.x0, e.x1 - f.axisX)),\n ),\n );\n return {\n inner,\n left: Math.max(inner + 1, f.axisX - f.shellLeft),\n right: Math.max(inner + 1, f.shellRight - f.axisX),\n };\n}\n\n/**\n * The front hair: over the face its bangs and the inner parts of its side\n * locks ride the face (and over the far eye, as far as that eye's corner\n * goes); out at the head's outline its outer edge follows only as far as\n * `hairOuter` — the outline is the back hair's, and holds —\n * the lock easing between. On a row where the back hair paints behind that\n * edge at every turn and nod angle, the edge rides further, up to the face's\n * follow, and on its cap less, so that the turn never carries the edge\n * further outside the back hair painted behind it than the nod alone does\n * (`outerRide`). Its crown, above the face plate's top, is the top of the\n * head: on the turn it rides with the cap as far as back hair is painted\n * behind its edges and gaps at every turn and nod angle, never baring the\n * face, and no row further than the one under it (`crownRide`); elsewhere it\n * eases toward its top to the back hair's motion, so the head's top outline\n * holds while the fringe slides under it. On the nod it eases to its cap\n * top's — one slide for the whole cap (`capSlide`), so the cap moves with the\n * face rather than its bangs stretching from a pinned top.\n */\nfunction hairFrontField(m: TurnModel): Field {\n const f = m.frame;\n const back = hairField(m, m.hairBack, NOD.hairBack);\n const cap = { up: NOD.hairFrontTop.up, down: capSlide(m) };\n // The rows the far eye's own lead reaches: its box, easing out over one\n // eye height above and below (the lock bends there, not over its length).\n const eyes = [m.boxes.eye_L, m.boxes.eye_R].filter(\n (e): e is Box => e !== undefined,\n );\n const { inner, left, right } = hairFrontBends(f, m.boxes);\n const eyeY =\n eyes.length > 0\n ? eyes.reduce((t, e) => t + cy(e), 0) / eyes.length\n : f.eyeY;\n const eyeH =\n eyes.length > 0\n ? eyes.reduce((t, e) => t + (e.y1 - e.y0), 0) / eyes.length\n : 1;\n // Turning toward s: from the near side's follow to the far eye's across\n // the face (on the eye's rows) ...\n const coreAt = (x: number, y: number, s: number) => {\n const u = s * (x - f.axisX);\n const across = Math.min(1, Math.max(0, (u + inner) / (2 * inner)));\n const band = 1 - smoothstep(eyeH / 2, 1.5 * eyeH, Math.abs(y - eyeY));\n return m.hairFront + (m.hairFar - m.hairFront) * across * band;\n };\n // ... then out to the outline's.\n const followAt = (x: number, y: number, s: number) => {\n const core = coreAt(x, y, s);\n const out = Math.min(\n 1,\n Math.max(\n 0,\n (Math.abs(x - f.axisX) - inner) /\n ((x < f.axisX ? left : right) - inner),\n ),\n );\n return core + (m.hairOuter - core) * out;\n };\n // The cap: the rows above the eyes and off the far eye's band.\n const ride = outerRide(m, inner, coreAt, followAt, eyeY + 1.5 * eyeH);\n const followOf = (x: number, y: number, s: number) =>\n followAt(x, y, s) + (ride === undefined ? 0 : ride.lift(x, y, s));\n // The front hair's own motion against the back hair's, along the turn.\n const drift = Math.abs(m.hairBack);\n const crown = crownRide(m, cap, (x, y, s) => followOf(x, y, s) + drift);\n // On the cap the follow gives up its local cut, then blends toward the\n // back hair's own motion (a follow of −drift).\n const boundOf = (x: number, y: number, s: number) => {\n if (ride === undefined) return followOf(x, y, s);\n const b = ride.blend(y, s);\n return (1 - b) * (followOf(x, y, s) + ride.cut(x, y, s)) - b * drift;\n };\n return (x, y, ax, ay) => {\n const s = Math.sign(ax);\n const a = Math.abs(ax) / 30;\n const rx =\n s * a * boundOf(x, y, s) + a * (m.shellScale - 1) * (x - f.axisX);\n const ry = nodDy(NOD.hairFront, ay, f.hh);\n const bx = back(x, y, ax, ay)[0];\n const by = nodDy(cap, ay, f.hh);\n const w = crownBlend(m, y);\n const wx = crown === undefined ? w : w + crown(y, s);\n return [bx + wx * (rx - bx), by + w * (ry - by)];\n };\n}\n\n/** The share of the front hair's own motion at model y, the rest its\n * crown's (on the turn, before `crownRide`'s extra): all of it up to the\n * face plate's top, none at the hair's top. */\nfunction crownBlend(m: TurnModel, y: number): number {\n const top = m.frame.face.y1;\n return 1 - smoothstep(top, Math.max(top + 1, m.hairTop), y);\n}\n\n/** Where model y falls among the evenly spaced vertex rows `ys` (top to\n * bottom), as the render interpolates between them: the row above it, `r`,\n * and its share `t` of the way to the next. With `snap`, a vertex — whose y\n * the mesh rounds to 1e-5 of its box — reads its own row alone. */\nfunction gridRow(\n ys: number[],\n y: number,\n snap = false,\n): { r: number; t: number } {\n const n = ys.length;\n let v = clamp(((ys[0] - y) / (ys[0] - ys[n - 1])) * (n - 1), 0, n - 1);\n if (snap && Math.abs(v - Math.round(v)) < 1e-3) v = Math.round(v);\n const r = Math.min(n - 2, Math.floor(v));\n return { r, t: v - r };\n}\n\n/** Where model x falls among the vertex columns `xs` (left to right): the\n * cell's left column, `c`, and its share `t` of the way across it. */\nfunction gridCol(xs: number[], x: number): { c: number; t: number } {\n let c = 0;\n while (c < xs.length - 2 && xs[c + 1] < x) c++;\n return { c, t: clamp((x - xs[c]) / (xs[c + 1] - xs[c]), 0, 1) };\n}\n\n/** The pixel rows, [first, end), indexed from the hair's top `ys[0]`, that\n * overlap the cells either side of vertex row r — none at or past `limit`. */\nfunction rowWindow(ys: number[], r: number, limit: number): [number, number] {\n const n = ys.length;\n return [\n Math.max(0, Math.floor(ys[0] - ys[Math.max(0, r - 1)])),\n Math.min(limit, Math.ceil(ys[0] - ys[Math.min(n - 1, r + 1)])),\n ];\n}\n\n/** The crown's blend at each of the front hair's vertex rows `ys` (top to\n * bottom), and between them as the render interpolates it. */\nfunction renderedCrownBlend(\n m: TurnModel,\n ys: number[],\n): { wr: number[]; blendAt: (y: number) => number } {\n const wr = ys.map((y) => crownBlend(m, y));\n return {\n wr,\n blendAt: (y) => {\n const { r, t } = gridRow(ys, y);\n return wr[r] + (wr[r + 1] - wr[r]) * t;\n },\n };\n}\n\n/** The most back-hair cover, hh, a crown column may lose at its top when the\n * cap's top slides looking down, beyond what it loses at the back hair's\n * own nod (the slide without runs): a pixel or two, so the slide opens no\n * notch in the head's top. The rest of the cap's slide is the art's to\n * earn, with a back hair drawn up past the front hair's top. */\nconst CAP_COVER_LOSS = 0.01;\n\n/**\n * How far the front hair's cap top slides looking down, hh at −30: one value\n * for the whole cap, the largest up to `NOD.hairFrontTop.down` at which no\n * crown column loses more than `CAP_COVER_LOSS` of back-hair cover beyond\n * what it loses at the back hair's own nod (`least`). Without both hair\n * layers' runs it is that nod.\n *\n * A column's top, its first opaque row, drops by the crown's blend of the\n * bangs' nod and the slide there, read between the mesh's vertex rows as the\n * render interpolates it (in the crown the drop depends on the row alone, so\n * across vertex columns it adds nothing). The pixel rows whose centres it\n * uncovers show the back hair at its own posed place, its nod lower, or\n * nothing; the cost is how many more show nothing than at `least`. It never\n * falls as the slide grows, so bisection finds the largest.\n */\nfunction capSlide(m: TurnModel): number {\n const f = m.frame;\n const least = NOD.hairBack.down;\n const grid = m.hairFrontGrid;\n if (\n grid === undefined ||\n f.hairRuns(\"hair_front\", grid.ys[0]) === undefined ||\n f.hairRuns(\"hair_back\", grid.ys[0]) === undefined\n ) {\n return least;\n }\n const { xs, ys } = grid;\n const top = ys[0];\n const n = ys.length;\n const bangs = NOD.hairFront.down;\n const { wr, blendAt } = renderedCrownBlend(m, ys);\n // From the first vertex row whose blend is 1 down, the slide moves nothing.\n const flat = ys[wr.findIndex((w) => w >= 1)] ?? ys[n - 1];\n // Each pixel column's top, in pixel rows under the hair's top: the first\n // row above `flat` that paints it.\n const x0 = xs[0];\n const tops = new Float64Array(Math.round(xs[xs.length - 1] - x0)).fill(NaN);\n for (let i = 0; i < top - flat; i++) {\n const runs = f.hairRuns(\"hair_front\", top - i - 0.5)!;\n for (let k = 0; k < runs.length; k += 2) {\n for (let px = runs[k]; px < runs[k + 1]; px++) {\n const j = Math.round(px - x0);\n if (Number.isNaN(tops[j])) tops[j] = i;\n }\n }\n }\n // The pixel rows under a column's top whose centres a drop of s px bares,\n // up to the most either nod, the bangs' or the cap top's, drops it.\n const hh = f.hh;\n const most = Math.ceil(Math.max(bangs, NOD.hairFrontTop.down) * hh);\n const bared = (s: number) => clamp(Math.ceil(s - 0.5), 0, most);\n const dropAt = (w: number, slide: number) =>\n (w * bangs + (1 - w) * slide) * hh;\n // Per crown column: its blend, how many of the first r rows under its top\n // the posed back hair leaves empty (`empty[r]`), and that at `least`.\n const backNod = NOD.hairBack.down * hh;\n const backRows = new Map<number, number[]>();\n const columns: { w: number; empty: Int32Array; base: number }[] = [];\n tops.forEach((i, j) => {\n if (Number.isNaN(i)) return;\n const w = blendAt(top - i);\n const empty = new Int32Array(most + 1);\n for (let r = 0; r < most; r++) {\n // The back hair's own pixel row behind that row's centre, its nod up.\n const at = Math.floor(i + r + 0.5 - backNod);\n let runs = backRows.get(at);\n if (runs === undefined) {\n runs = f.hairRuns(\"hair_back\", top - at - 0.5)!;\n backRows.set(at, runs);\n }\n empty[r + 1] = empty[r] + (paints(runs, x0 + j) ? 0 : 1);\n }\n columns.push({ w, empty, base: empty[bared(dropAt(w, least))] });\n });\n const budget = CAP_COVER_LOSS * hh;\n const fits = (slide: number) =>\n columns.every((c) => c.empty[bared(dropAt(c.w, slide))] - c.base <= budget);\n let lo: number = least;\n let hi: number = NOD.hairFrontTop.down;\n if (fits(hi)) return hi;\n // `least` always fits (it costs nothing); 30 halvings leave the slide far\n // finer than a keyform's rounding.\n for (let k = 0; k < 30; k++) {\n const mid = (lo + hi) / 2;\n if (fits(mid)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n\n/** Whether `runs` (model x boundaries) paint the pixel column starting at\n * model x `px`. */\nfunction paints(runs: number[], px: number): boolean {\n for (let k = 0; k < runs.length; k += 2) {\n if (runs[k] <= px && px + 1 <= runs[k + 1]) return true;\n }\n return false;\n}\n\ntype Follow = (x: number, y: number, s: number) => number;\n\n/** The front hair's outer edge against the back hair behind it, on the\n * turn (see `outerRide`). */\ninterface OuterRide {\n /** How much further than `followAt` the edge rides. */\n lift: Follow;\n /** On the cap, the follow a row gives up out toward its edge (≤ 0). */\n cut: Follow;\n /** On the cap, the share of a row's follow that blends toward the back\n * hair's own motion. */\n blend: (y: number, s: number) => number;\n}\n\n/** A bound edge of the cap, as a vertex row bounds it: its side, its own\n * column, the column the render reads the row at for it, and how far its\n * back hair's run reaches past it and inside it, the least over the nod. */\ninterface CapEdge {\n side: -1 | 1;\n x: number;\n at: number;\n outward: number;\n inward: number;\n}\n\n/**\n * The front hair's outer edge against the back hair painted behind it, at\n * (x, y) turning toward s; `undefined` unless both hair layers carry runs.\n *\n * On a pixel row, take the back hair's run holding the front's outermost\n * pixel on a side, on each back row the row passes over on the nod, read at\n * the edge's rest column: `c_in` the least it reaches inside the edge,\n * `c_out` the least past it (both 0 where the back hair is transparent there\n * on any of them, or where the edge rises above the back hair's top looking\n * up). Both layers take the shell's width term, and the back hair drifts\n * against the turn by |hairBack|; above the chin both roll rigidly with the\n * head, so the roll changes nothing between them.\n *\n * `lift`: how much further than `followAt` the edge rides where the back\n * hair stays behind it. On the far side the edge goes out, and stays over\n * that run's outer end while its follow is at most shellScale·c_out − drift;\n * on the near side it comes in, and the strip it leaves is that run while\n * its follow is at most shellScale·c_in − drift. The full turn binds both,\n * and the face's follow caps them. The render interpolates linearly between\n * the mesh's vertices, so each vertex row takes the smallest allowance among\n * the pixel rows within one row interval either side, and the innermost of\n * their edges: its ride is what the allowance leaves over today's follow\n * there, ramped from 0 at the eyes' outer corners (`inner`) to 1 at that\n * edge, and 1 beyond — a linear interpolation of that concave ramp never\n * exceeds it. A vertex row whose edges nothing covers rides nothing more:\n * today's hold.\n *\n * `cut` and `blend`: on its cap — the cells whose two vertex rows both lie\n * at or above `capLimit`, above the eyes and off the far eye's band — the\n * turn puts the edge no further outside the back hair than the nod alone\n * puts it. A cap row and side is bound where the back hair at rest paints\n * the pixel just inside the edge; elsewhere the front draws the outline\n * itself, and nothing bounds it. A bound edge moves against the back hair by\n * w × (its follow + drift), w the crown's blend at the vertex row (0 bounds\n * nothing), so its follow must lie in [−shellScale·c_back ÷ w − drift,\n * shellScale·c_fwd ÷ w − drift]: c_fwd the reach the way it moves against\n * the back hair (c_out turning toward its side, c_in away), c_back the\n * other. Where a reach is 0 the nod alone already shows the edge outside, so\n * the turn may add nothing; the back hair's own motion, a follow of −drift,\n * lies in every interval. The render reads a vertex row for a point between\n * rows at one column of the point's cell (its TL→BR split): at or toward −x\n * of the point on the row above, toward +x on the row below — inside the\n * edge on the row above and outside it on the row below on the +x side, the\n * reverse on −x — so each vertex row holds each bound edge in its window\n * where the render reads it there.\n *\n * On a cap row at or below the plate's top, where today's follow exceeds an\n * interval's upper end, the row first gives up a local cut: growing cell by\n * cell from the axis's cell out to the first vertex column at or past the\n * outermost bound edge in its window, constant beyond, each cell taking a\n * share proportional to a quarter of its width at a full turn (of its rest\n * width where the turn widens it), scaled to the least that meets every\n * bound edge and never past that quarter: no cell narrows below 3/4 of\n * today's width. Then each row blends toward the back hair's motion by the\n * least share that brings every bound edge in its window, on both sides,\n * inside its interval — on a crown row, the whole bound — and going up from\n * the plate's top no crown row blends less than the one under it. Both are\n * linear between vertex columns, so the render carries them. `crownRide`\n * still reads today's follow (`followAt` + `lift`), so its extra weight is\n * today's; the cut and the blend only lower the motion along the turn, so\n * its own bound still holds where that weight rides.\n *\n * So at every angle of the turn, the nod and the roll the cap's edge goes no\n * further outside the back hair than the nod alone puts it. Below the cap\n * the front hair keeps today's motion, so the lock over the far eye still\n * goes as far as that eye's corner and the turn solve's far-iris bound is\n * untouched; and the sway springs, which swing each layer by its own height,\n * are bounded by nothing.\n */\nfunction outerRide(\n m: TurnModel,\n inner: number,\n coreAt: Follow,\n followAt: Follow,\n capLimit: number,\n): OuterRide | undefined {\n const f = m.frame;\n const grid = m.hairFrontGrid;\n if (grid === undefined) return undefined;\n const { xs, ys } = grid;\n const top = ys[0];\n // Both layers must carry runs: `hairRuns` answers undefined on every row\n // of a layer without them, so any row tells.\n if (\n f.hairRuns(\"hair_front\", top) === undefined ||\n f.hairRuns(\"hair_back\", top) === undefined\n ) {\n return undefined;\n }\n const drift = Math.abs(m.hairBack);\n const sides = [-1, 1] as const;\n const n = ys.length;\n const count = Math.round(top - ys[n - 1]);\n // The cap's last vertex row (0: no cap), and its pixel rows: those whose\n // centres lie on or above that row.\n let last = 0;\n while (last + 1 < n && ys[last + 1] >= capLimit) last++;\n const capRows =\n last === 0 ? 0 : Math.min(count, Math.floor(top - ys[last] - 0.5) + 1);\n // On the nod a front row passes over the back hair's rows: down by the\n // bangs' nod less the back hair's looking down, up by theirs looking up\n // (the crown, easing to the cap's smaller nod, passes over fewer). The\n // back's pixel rows, indexed as the front's from its top, from `j0`.\n const below = (NOD.hairFront.down - NOD.hairBack.down) * f.hh;\n const above = (NOD.hairBack.up - NOD.hairFront.up) * f.hh;\n const j0 = Math.floor(-above);\n const backRows = Array.from(\n { length: Math.ceil(count + below) - j0 },\n (_, j) => f.hairRuns(\"hair_back\", top - (j + j0) - 0.5)!,\n );\n // Per pixel row of the front hair's crop and side (−x, +x): the edge's\n // offset from the axis (NaN without one there), its back hair's least\n // reaches past it and inside it, and on the cap whether it is bound.\n const offset = sides.map(() => new Float64Array(count).fill(NaN));\n const reachOut = sides.map(() => new Float64Array(count));\n const reachIn = sides.map(() => new Float64Array(count));\n const bound = sides.map(() => new Uint8Array(count));\n for (let i = 0; i < count; i++) {\n const y = top - i - 0.5;\n const front = f.hairRuns(\"hair_front\", y)!;\n sides.forEach((side, k) => {\n const edge = outerEdge(front, f.axisX, side);\n if (edge === undefined) return;\n // The least reach over every back row the row's span overlaps at some\n // nod: a turn and a nod add.\n let outward = Infinity;\n let inward = Infinity;\n for (let j = Math.floor(i - above); j < Math.ceil(i + 1 + below); j++) {\n const c = runReach(backRows[j - j0], edge, side);\n outward = Math.min(outward, c.outward);\n inward = Math.min(inward, c.inward);\n }\n offset[k][i] = side * (edge - f.axisX);\n reachOut[k][i] = outward;\n reachIn[k][i] = inward;\n if (i < capRows && runReach(backRows[i - j0], edge, side).inward > 0)\n bound[k][i] = 1;\n });\n }\n // Per vertex row and side: the innermost edge in its window, and the ride\n // turning toward −x and toward +x.\n const end = new Float64Array(n * 2);\n const lift = new Float64Array(n * 4);\n for (let r = 0; r < n; r++) {\n const [i0, i1] = rowWindow(ys, r, count);\n sides.forEach((side, k) => {\n let d = Infinity;\n let outward = Infinity;\n let inward = Infinity;\n for (let i = i0; i < i1; i++) {\n if (Number.isNaN(offset[k][i])) continue;\n d = Math.min(d, offset[k][i]);\n outward = Math.min(outward, reachOut[k][i]);\n inward = Math.min(inward, reachIn[k][i]);\n }\n end[r * 2 + k] = d;\n if (d === Infinity || d <= inner) return;\n const x = f.axisX + side * d;\n sides.forEach((s, j) => {\n const allow = Math.min(\n coreAt(x, ys[r], s),\n m.shellScale * (s === side ? outward : inward) - drift,\n );\n lift[(r * 2 + k) * 2 + j] = Math.max(0, allow - followAt(x, ys[r], s));\n });\n });\n }\n const rowRide = (r: number, k: number, j: number, d: number) => {\n const v = lift[(r * 2 + k) * 2 + j];\n return v === 0\n ? 0\n : v * Math.min(1, (d - inner) / (end[r * 2 + k] - inner));\n };\n const liftAt: Follow = (x, y, s) => {\n const d = Math.abs(x - f.axisX);\n if (s === 0 || d <= inner) return 0;\n const k = x < f.axisX ? 0 : 1;\n const j = s < 0 ? 0 : 1;\n // Between vertex rows, as the render interpolates; a vertex reads its\n // own row's ride alone.\n const { r, t } = gridRow(ys, y, true);\n return rowRide(r, k, j, d) * (1 - t) + rowRide(r + 1, k, j, d) * t;\n };\n\n // --- the cap ---\n const nc = xs.length;\n /** Linear between vertex columns, as the render reads a row's values. */\n const along = (v: ArrayLike<number>, x: number) => {\n const { c, t } = gridCol(xs, x);\n return v[c] + (v[c + 1] - v[c]) * t;\n };\n /** Where the render reads vertex row r for the point (x, y), within x's\n * cell: at or toward −x of x in the cell under r, toward +x in the cell\n * above it; undefined where r has no weight there. */\n const readAt = (r: number, x: number, y: number): number | undefined => {\n const { c, t: fx } = gridCol(xs, x);\n const dx = xs[c + 1] - xs[c];\n if (r + 1 < n && y <= ys[r] && y >= ys[r + 1]) {\n const fy = (ys[r] - y) / (ys[r] - ys[r + 1]);\n if (fy >= 1) return undefined;\n return fx <= fy ? xs[c] : xs[c] + ((fx - fy) / (1 - fy)) * dx;\n }\n if (r > 0 && y > ys[r] && y < ys[r - 1]) {\n const fy = (ys[r - 1] - y) / (ys[r - 1] - ys[r]);\n return fx <= fy ? xs[c] + (fx / fy) * dx : xs[c + 1];\n }\n return undefined;\n };\n // Turning toward s a bound edge moves against the back hair toward s: out\n // past its run on the side it turns toward, in on the other. Its reach\n // that way, and the other.\n const ahead = (e: CapEdge, s: number) =>\n s === e.side ? e.outward : e.inward;\n const behind = (e: CapEdge, s: number) =>\n s === e.side ? e.inward : e.outward;\n /**\n * The local cut on vertex row r turning toward s, on `side` (its bound\n * edges `mine`; `today` the row's follow at each vertex column): each\n * cell's quarter of its width at a full turn (of its rest width where the\n * turn widens it), summed cell by cell from the axis's cell out to the\n * first vertex column at or past the outermost of those edges, constant\n * beyond, and scaled to the least that brings every edge to its interval's\n * upper end, never past that quarter. Per vertex column; 0 on the other\n * side.\n */\n const capCut = (\n r: number,\n s: number,\n side: -1 | 1,\n today: number[],\n mine: CapEdge[],\n ): Float64Array => {\n const reach = Math.max(...mine.map((e) => side * (e.x - f.axisX)));\n const quarter = new Float64Array(nc);\n const cols = xs\n .map((_, c) => c)\n .filter((c) => (xs[c] < f.axisX ? -1 : 1) === side);\n if (side < 0) cols.reverse();\n let total = 0;\n let x0 = f.axisX;\n let d0 = s * followAt(f.axisX, ys[r], s);\n let open = true;\n for (const c of cols) {\n if (open) {\n const d = (m.shellScale - 1) * (xs[c] - f.axisX) + s * today[c];\n const rest = side * (xs[c] - x0);\n const full = rest + side * (d - d0);\n total += Math.max(0, Math.min(full, rest)) / 4;\n x0 = xs[c];\n d0 = d;\n open = side * (xs[c] - f.axisX) < reach;\n }\n quarter[c] = total;\n }\n let scale = 0;\n for (const e of mine) {\n const need = along(today, e.at) - (m.shellScale * ahead(e, s) - drift);\n if (need <= 0) continue;\n const q = along(quarter, e.at);\n scale = Math.max(scale, q > 0 ? need / q : 1);\n }\n scale = Math.min(1, scale);\n return quarter.map((q) => scale * q);\n };\n // Per vertex row and direction: the cut at each vertex column, and the\n // blend.\n const cuts = new Float64Array(n * 2 * nc);\n const blend = new Float64Array(n * 2);\n const wr = ys.map((y) => crownBlend(m, y));\n for (let r = 0; r <= last && capRows > 0; r++) {\n const w = wr[r];\n if (w <= 0) continue;\n // The bound edges in the row's window, each where the render reads the\n // row for it.\n const edges: CapEdge[] = [];\n const [i0, i1] = rowWindow(ys, r, capRows);\n for (let i = i0; i < i1; i++) {\n sides.forEach((side, k) => {\n if (bound[k][i] === 0) return;\n const x = f.axisX + side * offset[k][i];\n const at = readAt(r, x, top - i - 0.5);\n if (at === undefined) return;\n edges.push({\n side,\n x,\n at,\n outward: reachOut[k][i],\n inward: reachIn[k][i],\n });\n });\n }\n if (edges.length === 0) continue;\n sides.forEach((s, j) => {\n // Today's follow at each vertex column, and after the cut.\n const today = xs.map((x) => followAt(x, ys[r], s) + liftAt(x, ys[r], s));\n const after = today.slice();\n if (w >= 1) {\n for (const side of sides) {\n const mine = edges.filter((e) => e.side === side);\n if (mine.length === 0) continue;\n const cut = capCut(r, s, side, today, mine);\n for (let c = 0; c < nc; c++) after[c] -= cut[c];\n }\n }\n let b = 0;\n for (const e of edges) {\n const rel = w * (along(after, e.at) + drift);\n const hi = m.shellScale * ahead(e, s);\n const lo = -m.shellScale * behind(e, s);\n if (rel > hi) b = Math.max(b, 1 - hi / rel);\n else if (rel < lo) b = Math.max(b, 1 - lo / rel);\n }\n blend[r * 2 + j] = b;\n for (let c = 0; c < nc; c++)\n cuts[(r * 2 + j) * nc + c] = after[c] - today[c];\n });\n }\n // Up from the plate's top, no crown row blends less than the one under it.\n for (let j = 0; j < 2; j++) {\n for (let r = n - 2; r >= 0; r--) {\n if (wr[r] < 1)\n blend[r * 2 + j] = Math.max(blend[r * 2 + j], blend[(r + 1) * 2 + j]);\n }\n }\n const cutRow = (r: number, j: number, x: number) =>\n r > last\n ? 0\n : along(cuts.subarray((r * 2 + j) * nc, (r * 2 + j + 1) * nc), x);\n return {\n lift: liftAt,\n // Between vertex rows, as the render interpolates; a vertex reads its own\n // row's alone.\n cut: (x, y, s) => {\n if (s === 0) return 0;\n const j = s < 0 ? 0 : 1;\n const { r, t } = gridRow(ys, y, true);\n return cutRow(r, j, x) * (1 - t) + cutRow(r + 1, j, x) * t;\n },\n blend: (y, s) => {\n if (s === 0) return 0;\n const j = s < 0 ? 0 : 1;\n const { r, t } = gridRow(ys, y, true);\n return blend[r * 2 + j] * (1 - t) + blend[(r + 1) * 2 + j] * t;\n },\n };\n}\n\n/**\n * How much of the front hair's own motion the crown takes on the turn at\n * model y turning toward s, beyond `crownBlend`'s; `undefined` unless both\n * hair layers carry runs.\n *\n * Eased to the back hair's motion, the crown uncovers nothing new. Riding\n * further, each of its boundaries moves against the back hair, and must\n * uncover no background and no skin, at any angle of the turn and the nod.\n * On a pixel row, the far outer edge goes out, and must stay over the back's\n * run past it (`c_out`); every trailing boundary — a run's start turning\n * toward +x, its end toward −x: each gap's sides and the near outer edge —\n * leaves a strip the back's run inside it must fill (`c_in`). Each reach is\n * the least over the back rows the row passes over on its own nod (the\n * crown's rendered blend of the bangs' nod and the cap top's, less the back\n * hair's), and both layers take the shell's width term. The face lies in\n * front of the back hair: a trailing strip that meets a face run at the same\n * angle of the turn, on a face row it passes over on the nod relative to the\n * face, would bare skin, so nothing backs it.\n *\n * The render mixes vertex values with non-negative weights, so a boundary\n * moves against the back hair at most R × the rendered weight there, R the\n * largest motion against it (`relAt`) of the four vertices of its cell. Each\n * crown vertex row therefore takes the least allowance ÷ R − today's rendered\n * blend over the pixel rows within one row interval either side, between 0\n * and what brings it to the front hair's own motion: each boundary moves at\n * most today's motion plus its slack. An R of 0 bounds nothing. Then, up from\n * the plate's top, no row rides further than the one under it, so the cap's\n * outline does not shear.\n */\nfunction crownRide(\n m: TurnModel,\n cap: Nod,\n relAt: Follow,\n): ((y: number, s: number) => number) | undefined {\n const f = m.frame;\n const grid = m.hairFrontGrid;\n if (grid === undefined) return undefined;\n const { xs, ys } = grid;\n const top = ys[0];\n // Both layers must carry runs, as `outerRide` checks them.\n if (\n f.hairRuns(\"hair_front\", top) === undefined ||\n f.hairRuns(\"hair_back\", top) === undefined\n ) {\n return undefined;\n }\n const n = ys.length;\n const count = Math.round(top - ys[n - 1]);\n const hh = f.hh;\n const face = faceField(m);\n const { wr, blendAt } = renderedCrownBlend(m, ys);\n // The back hair's and the face's runs on pixel row j, indexed as the\n // front's from its top. Without the face's runs, its crop stands in.\n const backRows = new Map<number, number[]>();\n const backAt = (j: number) => {\n let runs = backRows.get(j);\n if (runs === undefined) {\n runs = f.hairRuns(\"hair_back\", top - j - 0.5)!;\n backRows.set(j, runs);\n }\n return runs;\n };\n const faceAt = (j: number) => {\n const y = top - j - 0.5;\n return (\n f.faceRuns(y) ??\n (y > f.face.y0 && y < f.face.y1 ? [f.face.x0, f.face.x1] : [])\n );\n };\n // The pixel rows row i overlaps at rest and moved by each of `dys` (model\n // dy, y up), as [first, end).\n const passed = (i: number, dys: number[]) => [\n Math.floor(i - Math.max(0, ...dys)),\n Math.ceil(i + 1 - Math.min(0, ...dys)),\n ];\n // relAt at each vertex, per side.\n const rel = new Float64Array(n * xs.length * 2).fill(NaN);\n const relOf = (r: number, c: number, k: number) => {\n const at = (r * xs.length + c) * 2 + k;\n if (Number.isNaN(rel[at])) rel[at] = relAt(xs[c], ys[r], k === 0 ? -1 : 1);\n return rel[at];\n };\n const cellR = (x: number, y: number, k: number) => {\n const { c } = gridCol(xs, x);\n const { r } = gridRow(ys, y);\n return Math.max(\n relOf(r, c, k),\n relOf(r, c + 1, k),\n relOf(r + 1, c, k),\n relOf(r + 1, c + 1, k),\n );\n };\n /** Whether c0 + a·c1 > 0 for every pair at some angle a in (0, 1]. */\n const someAngle = (pairs: [number, number][]) => {\n let lo = 0;\n let hi = 1;\n for (const [c0, c1] of pairs) {\n if (c1 === 0) {\n if (c0 <= 0) return false;\n } else if (c1 > 0) lo = Math.max(lo, -c0 / c1);\n else hi = Math.min(hi, -c0 / c1);\n }\n return lo < hi;\n };\n // Per pixel row and side (−x, +x): the least allowance ÷ R over its\n // bounded boundaries, less today's rendered blend there.\n const slack = [-1, 1].map(() => new Float64Array(count).fill(NaN));\n const slackAt = (i: number, k: number) => {\n if (!Number.isNaN(slack[k][i])) return slack[k][i];\n const y = top - i - 0.5;\n const w = blendAt(y);\n const nod: Nod = {\n up: w * NOD.hairFront.up + (1 - w) * cap.up,\n down: w * NOD.hairFront.down + (1 - w) * cap.down,\n };\n const ays = [-30, 30];\n const [b0, b1] = passed(\n i,\n ays.map((ay) => nodDy(nod, ay, hh) - nodDy(NOD.hairBack, ay, hh)),\n );\n const band: number[][] = [];\n for (let j = b0; j < b1; j++) band.push(backAt(j));\n // The face's rows and runs the row passes over relative to the face on\n // the nod — from just above the plate's top too, looking down: the bangs\n // drop further than the face there.\n const faces: { y: number; runs: number[] }[] = [];\n const [f0, f1] = passed(\n i,\n ays.map((ay) => nodDy(nod, ay, hh) - face(f.axisX, y, 0, ay)[1]),\n );\n for (let j = f0; j < f1; j++)\n faces.push({ y: top - j - 0.5, runs: faceAt(j) });\n const front = f.hairRuns(\"hair_front\", y)!;\n ([-1, 1] as const).forEach((s, side) => {\n let least = Infinity;\n const far = outerEdge(front, f.axisX, s);\n if (far !== undefined) {\n const R = cellR(far, y, side);\n const c = Math.min(...band.map((b) => runReach(b, far, s).outward));\n if (R > 0) least = Math.min(least, (m.shellScale * c) / R);\n }\n for (let t = s > 0 ? 0 : 1; t < front.length; t += 2) {\n const x = front[t];\n const R = cellR(x, y, side);\n if (R <= 0) continue;\n // A trailing boundary is its run's edge on the −s side; read as an\n // outer edge there, `inward` is how far the back's run reaches into\n // the strip it leaves.\n let c = Math.min(\n ...band.map((b) => runReach(b, x, s > 0 ? -1 : 1).inward),\n );\n // At angle a the strip lies between x moved by a × the front hair's\n // displacement at the least crown weight (the back hair's drift) and\n // at the most (the cell's largest follow), each with the shell term;\n // a face run between its ends moved by a × `faceField`'s at a full\n // turn. Every end moves linearly in a, so the angles at which the two\n // overlap are one interval.\n const sh = (m.shellScale - 1) * (x - f.axisX);\n const d0 = sh + s * m.hairBack;\n const d1 = d0 + s * R;\n const lo = Math.min(d0, d1);\n const hi = Math.max(d0, d1);\n const bares = faces.some(({ y: fy, runs }) => {\n for (let r = 0; r < runs.length; r += 2) {\n const e0 = runs[r];\n const e1 = runs[r + 1];\n const de0 = face(e0, fy, 30 * s, 0)[0];\n const de1 = face(e1, fy, 30 * s, 0)[0];\n if (\n someAngle([\n [e1 - x, de1 - lo],\n [x - e0, hi - de0],\n ])\n ) {\n return true;\n }\n }\n return false;\n });\n if (bares) c = 0;\n least = Math.min(least, (m.shellScale * c) / R);\n }\n slack[side][i] = least - w;\n });\n return slack[k][i];\n };\n // Per side, each crown vertex row's extra weight, then the monotone pass\n // up from the plate's top.\n const extra = [0, 1].map((k) => {\n const out = wr.slice();\n for (let r = 0; r < n; r++) {\n if (wr[r] >= 1) continue;\n const [i0, i1] = rowWindow(ys, r, count);\n let least = Infinity;\n for (let i = i0; i < i1; i++) least = Math.min(least, slackAt(i, k));\n out[r] = wr[r] + clamp(least, 0, 1 - wr[r]);\n }\n for (let r = n - 2; r >= 0; r--) {\n if (wr[r] < 1) out[r] = Math.max(wr[r], Math.min(out[r], out[r + 1]));\n }\n return out.map((v, r) => v - wr[r]);\n });\n return (y, s) => {\n if (s === 0) return 0;\n const e = extra[s < 0 ? 0 : 1];\n // Between vertex rows, as the render interpolates; a vertex reads its own\n // row's alone.\n const { r, t } = gridRow(ys, y, true);\n return e[r] * (1 - t) + e[r + 1] * t;\n };\n}\n\n/** The field a family moves by (AngleZ 0: the roll is the head deformer's). */\nexport function familyField(m: TurnModel, family: Family): Field {\n switch (family) {\n case \"face\":\n return faceField(m);\n case \"eye_L\":\n case \"eye_R\":\n return eyeField(m, m.boxes[family]!);\n case \"brow_L\":\n case \"brow_R\":\n return browField(m, m.boxes[family]!);\n case \"nose\":\n return noseField(m);\n case \"mouth\":\n return mouthField(m);\n case \"hair_front\":\n return hairFrontField(m);\n case \"hair_back\":\n return hairField(m, m.hairBack, NOD.hairBack);\n case \"body\":\n case \"arm\":\n // The torso and the arms have no turn field of their own: the body\n // warp (`body.ts`) moves them.\n return () => [0, 0];\n }\n}\n","/**\n * The face plate's mesh: the head, and — when the face layer paints them — the\n * neck and the ears as further islands of the same drawing, drawn first so the\n * head slides over them. The head island ends just under the jaw's outline and\n * along the head's own outline under each ear; the neck island runs from the\n * collar up under the jaw, its hidden top stretching the neck's first rows\n * under the jaw upward, so a chin sliding off it uncovers neck rather than the\n * chin painted there; each ear island reaches in under the head a little —\n * on the near side that tuck rides the head, on the far side it slides deeper\n * under it as the ear lags — so an ear never opens a gap beside it.\n */\n\nimport type { IkiMesh } from \"@ikijs/format\";\nimport { fadeToOutline, type HeadFrame } from \"./head\";\nimport {\n bh,\n bw,\n cellsFor,\n clamp,\n cx,\n cy,\n roundTo,\n type Box,\n type Cells,\n} from \"./layout\";\nimport { AMPLITUDE } from \"./profile\";\n\nexport type Region = \"head\" | \"neck\" | \"ear\";\n\nexport interface FaceMesh {\n mesh: IkiMesh;\n /** Per vertex: the island it belongs to. */\n region: Region[];\n /** The head island's triangles start at this index into `mesh.indices`. */\n headStart: number;\n}\n\n/** How far below the cut the neck's hidden top samples the drawing, hh: in\n * the neck's shade, clear of the jaw's own line and its darkest band, so the\n * neck a chin uncovers is one even tone. */\nconst SAMPLE_BELOW = 0.04;\n/** How far an ear island reaches in under the head's outline, hh: enough to\n * stay under the head island's edge, which follows that line only through\n * the island's columns and strays a little either side of it between them.\n * On the near side the tuck rides the head; on the far side it slides\n * deeper under it as the ear lags. */\nconst EAR_TUCK = 0.08;\n\nexport function buildFaceMesh(\n frame: HeadFrame,\n b: Box,\n head: Cells,\n neckCells: Cells,\n): FaceMesh {\n const vertices: number[] = [];\n const uvs: number[] = [];\n const region: Region[] = [];\n const pos: [number, number][] = [];\n const add = (x: number, y: number, uy: number, r: Region): number => {\n vertices.push(\n roundTo((x - cx(b)) / bw(b), 1e-5),\n roundTo((y - cy(b)) / bh(b), 1e-5),\n );\n uvs.push(\n roundTo((x - b.x0) / bw(b), 1e-5),\n roundTo((b.y1 - uy) / bh(b), 1e-5),\n );\n region.push(r);\n pos.push([x, y]);\n return region.length - 1;\n };\n // A cell's two triangles, less either one with no area (a column that\n // lies wholly outside the head collapses to its top).\n const quad = (\n out: number[],\n tl: number,\n tr: number,\n bl: number,\n br: number,\n ) => {\n for (const [p, q, t] of [\n [bl, br, tl],\n [tl, br, tr],\n ]) {\n // Two corners on one spot (a collapsed column's rows) make a sliver\n // that only rounding gives an area.\n const apart = (i: number, j: number) =>\n Math.hypot(pos[i][0] - pos[j][0], pos[i][1] - pos[j][1]) > 0.5;\n const area =\n (pos[q][0] - pos[p][0]) * (pos[t][1] - pos[p][1]) -\n (pos[t][0] - pos[p][0]) * (pos[q][1] - pos[p][1]);\n if (apart(p, q) && apart(q, t) && apart(p, t) && Math.abs(area) > 0.5)\n out.push(p, q, t);\n }\n };\n const pad = 3 + 0.1 * frame.wMax;\n // Whether the plate's paint reaches into [x0, x1] on any row between yTop\n // and yBot (its row spans are half-widths about the axis, so an off-centre\n // row gets the pad).\n const painted = (\n x0: number,\n x1: number,\n yTop: number,\n yBot: number,\n ): boolean => {\n for (let i = 0; i <= 8; i++) {\n const y = yTop + ((yBot - yTop) * i) / 8;\n const w = frame.paintedHalfAt(y) + pad;\n if (x1 >= frame.axisX - w && x0 <= frame.axisX + w) return true;\n }\n return false;\n };\n\n // A lattice whose rows run between a per-column top and bottom, cells kept\n // by `keep`; returns its triangles.\n const island = (\n xs: number[],\n rowsOf: (x: number) => { y: number; uy: number }[],\n r0: Region,\n keep: (c: number, r: number, col: { y: number }[][]) => boolean,\n ): number[] => {\n const cols = xs.map((x) => rowsOf(x));\n const ids = cols.map((col, c) => col.map((p) => add(xs[c], p.y, p.uy, r0)));\n const out: number[] = [];\n const rows = cols[0].length - 1;\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c + 1 < xs.length; c++) {\n if (!keep(c, r, cols)) continue;\n quad(out, ids[c][r], ids[c + 1][r], ids[c][r + 1], ids[c + 1][r + 1]);\n }\n }\n return out;\n };\n\n // Columns at even steps, plus the chin's and the jaw corners' own, so the\n // cut's V runs through vertices rather than chording off its tip, and the\n // chin's shade band's ends, so no cell chords the band on past them.\n const columns = (x0: number, x1: number, n: number): number[] => {\n const xs = Array.from(\n { length: n + 1 },\n (_, c) => x0 + ((x1 - x0) * c) / n,\n );\n const neck = frame.neck;\n const step = (x1 - x0) / n;\n // The head's own widest reach (its ears left out): past it a column is\n // wholly outside the head, and the head island must still reach it.\n const at = [\n frame.axisX - frame.headMax + 0.5,\n frame.axisX + frame.headMax - 0.5,\n ];\n if (neck !== undefined) {\n at.push(\n frame.axisX,\n frame.axisX - neck.half,\n frame.axisX + neck.half,\n frame.axisX - neck.waist,\n frame.axisX + neck.waist,\n );\n if (neck.bandEnd !== undefined)\n at.push(frame.axisX - neck.bandEnd, frame.axisX + neck.bandEnd);\n }\n // Each takes the even column near it (not an end), or one of its own —\n // never a column another has taken, so none of them is lost; one near an\n // end is left to it, and one within half a pixel of a taken column is that\n // column.\n const placed = new Set<number>();\n for (const k of at) {\n if (k <= x0 || k >= x1) continue;\n if ([...placed].some((i) => Math.abs(xs[i] - k) < 0.5)) continue;\n const near = xs.findIndex(\n (x, i) => !placed.has(i) && Math.abs(x - k) < 0.3 * step,\n );\n if (near > 0 && near < n) {\n xs[near] = k;\n placed.add(near);\n } else if (near < 0) placed.add(xs.push(k) - 1);\n }\n return xs.sort((a, b) => a - b);\n };\n\n const indices: number[] = [];\n const neck = frame.neck;\n if (neck !== undefined) {\n const span = neck.span + pad;\n const nc = cellsFor(2 * span, neckCells.px, neckCells.min, neckCells.max);\n // Inside the crop: a collar flaring nearly as wide as the plate must not\n // put a vertex's texture off it.\n const xs = columns(\n Math.max(b.x0, frame.axisX - span),\n Math.min(b.x1, frame.axisX + span),\n nc,\n );\n // The hidden rows show the drawing SAMPLE_BELOW under the cut, thinning\n // to the row just under it at the neck's outline (which must run on\n // unbroken above the cut). Under the chin that is the neck below the\n // shade band the head carries; past the band's end, where the cut runs\n // just under the stroke, it is whatever shade the neck keeps there.\n const sampleBelow = (x: number) =>\n Math.max(\n 1,\n SAMPLE_BELOW *\n frame.hh *\n fadeToOutline(Math.abs(x - frame.axisX), neck),\n );\n // The jaw's corners: the highest the cut runs across the neck. Beside\n // the neck a column's cut is the head's own side outline instead, up the\n // cheek (or, past the head's widest reach, the plate's top): there the\n // island only carries what the plate paints under the jaw's corners — a\n // collar's flare — or it would hold a still copy of the cheek beside the\n // turning head.\n let highest = -Infinity;\n for (const x of xs) {\n if (Math.abs(x - frame.axisX) <= neck.half)\n highest = Math.max(highest, frame.cutAt(x));\n }\n const cutOf = (x: number) => Math.min(frame.cutAt(x), highest);\n // One level top, above the jaw's corners: a top following the jaw's V\n // would show its own diagonal edge once the chin slides and lifts off it.\n const top = Math.min(b.y1, highest + AMPLITUDE.hiddenNeck * frame.hh);\n const realRows = cellsFor(\n highest - b.y0,\n neckCells.px,\n neckCells.min,\n neckCells.max,\n );\n // Two rows reaching up under the jaw, a third a pixel above the cut, all\n // showing the neck's shade; then the neck as drawn, from the cut down.\n const hiddenRows = 3;\n indices.push(\n ...island(\n xs,\n (x) => {\n const cut = cutOf(x);\n const sample = Math.max(b.y0, cut - sampleBelow(x));\n const pts: { y: number; uy: number }[] = [\n { y: top, uy: sample },\n { y: (top + cut) / 2, uy: sample },\n { y: cut + 1, uy: sample },\n { y: cut, uy: cut },\n ];\n // Level rows, shared by every column (a column's own rows above\n // its cut collapse onto it): the neck's cells stay square rather\n // than slanting with the jaw's V.\n for (let r = 1; r <= realRows; r++) {\n const y = Math.min(\n cut,\n highest - ((highest - b.y0) * r) / realRows,\n );\n pts.push({ y, uy: y });\n }\n return pts;\n },\n \"neck\",\n (c, r, cols) => {\n const top = Math.max(cols[c][r].y, cols[c + 1][r].y);\n const bot = Math.min(cols[c][r + 1].y, cols[c + 1][r + 1].y);\n if (r < hiddenRows) {\n // The hidden rows show the drawing just under the jaw.\n const mid = (xs[c] + xs[c + 1]) / 2;\n const y = Math.max(b.y0, cutOf(mid) - sampleBelow(mid));\n return painted(xs[c], xs[c + 1], y, y);\n }\n return painted(xs[c], xs[c + 1], top, bot);\n },\n ),\n );\n }\n const ears = frame.ears;\n if (ears !== undefined) {\n // Rows over the band, each running from under the head's outline (by\n // EAR_TUCK) out past the ear.\n const tuck = EAR_TUCK * frame.hh;\n const yTop = Math.min(b.y1, ears.top + 2);\n const yBot = Math.max(b.y0, ears.bottom - 2);\n const nr = cellsFor(yTop - yBot, 16, 3, 10);\n const outer = ears.outer + pad;\n let inner = Infinity;\n for (let r = 0; r <= nr; r++)\n inner = Math.min(inner, ears.attachAt(yTop - ((yTop - yBot) * r) / nr));\n const nc = cellsFor(outer - (inner - tuck), 12, 2, 6);\n for (const side of [-1, 1] as const) {\n const ids: number[][] = [];\n const xsOf: number[][] = [];\n for (let r = 0; r <= nr; r++) {\n const y = yTop - ((yTop - yBot) * r) / nr;\n const d0 = Math.max(0, ears.attachAt(y) - tuck);\n const row: number[] = [];\n const xs: number[] = [];\n for (let c = 0; c <= nc; c++) {\n // Left to right whichever side, so the cells wind as the head's.\n const k = side < 0 ? nc - c : c;\n const x = clamp(\n frame.axisX + side * (d0 + ((outer - d0) * k) / nc),\n b.x0,\n b.x1,\n );\n xs.push(x);\n row.push(add(x, y, y, \"ear\"));\n }\n ids.push(row);\n xsOf.push(xs);\n }\n for (let r = 0; r < nr; r++) {\n for (let c = 0; c < nc; c++) {\n const x0 = Math.min(xsOf[r][c], xsOf[r + 1][c]);\n const x1 = Math.max(xsOf[r][c + 1], xsOf[r + 1][c + 1]);\n const yt = yTop - ((yTop - yBot) * r) / nr;\n const yb = yTop - ((yTop - yBot) * (r + 1)) / nr;\n if (!painted(x0, x1, yt, yb)) continue;\n quad(\n indices,\n ids[r][c],\n ids[r][c + 1],\n ids[r + 1][c],\n ids[r + 1][c + 1],\n );\n }\n }\n }\n }\n\n const headStart = indices.length;\n const cols = cellsFor(bw(b), head.px, head.min, head.max);\n const rows = cellsFor(bh(b), head.px, head.min, head.max);\n const xs = columns(b.x0, b.x1, cols);\n indices.push(\n ...island(\n xs,\n (x) => {\n const bottom = Math.max(b.y0, frame.cutAt(x));\n return Array.from({ length: rows + 1 }, (_, r) => {\n const y = b.y1 - ((b.y1 - bottom) * r) / rows;\n return { y, uy: y };\n });\n },\n \"head\",\n (c, r, cols) => {\n // A column wholly outside the head (past the ears' reach, beside the\n // neck) has collapsed to its top: fanning cells out of it would\n // sweep over the ear.\n const height = (k: number) =>\n cols[k][0].y - cols[k][cols[k].length - 1].y;\n if (height(c) < 1 || height(c + 1) < 1) return false;\n return painted(\n xs[c],\n xs[c + 1],\n Math.max(cols[c][r].y, cols[c + 1][r].y),\n Math.min(cols[c][r + 1].y, cols[c + 1][r + 1].y),\n );\n },\n ),\n );\n return { mesh: { vertices, uvs, indices }, region, headStart };\n}\n","/**\n * Turning the profile into this character's turn, fitting any cue a caller\n * measured, keeping the features inside the art's room, and reporting what\n * the rig then renders.\n *\n * With no target the turn is the profile's (times the style's knobs). A given\n * cue is fitted by the one knob it reads: eyeShift by the turn's amount,\n * farEyeRatio by the eyes' foreshortening, silhouetteRatio by the hair's\n * width, noseShift and mouthShift by those features' own shift. The room the\n * art leaves — the far eye inside the plate's outline, the far iris clear of\n * the bangs' side strand, the nose and mouth inside the plate, the far ear's\n * slide under the head — caps the turn (or that feature, or the plate's\n * narrowing) and says so in `clamped`.\n */\n\nimport type { HeadFrame } from \"./head\";\nimport { cy, type Box } from \"./layout\";\nimport { roleSpec, type Family } from \"./roles\";\nimport {\n chinSlide,\n familyField,\n farEarCovered,\n type TurnModel,\n} from \"./fields\";\nimport { TURN, type ResolvedStyle } from \"./profile\";\nimport {\n TurnTargetError,\n type IrisStrand,\n type StrandOverlap,\n type TurnSolveReport,\n type TurnTargets,\n} from \"./types\";\n\n// --- targets ----------------------------------------------------------------\n\nexport type ResolvedTargets = Partial<Record<keyof TurnTargets, number>> & {\n /** The fields the caller passed. */\n given: Set<keyof TurnTargets>;\n};\n\nconst RANGES: Record<keyof TurnTargets, [number, number, boolean]> = {\n // [lo, hi, lo exclusive]\n eyeShift: [-1, 1, false],\n farEyeRatio: [0, 1.5, true],\n silhouetteRatio: [0.5, 1.5, false],\n noseShift: [-1, 1, false],\n mouthShift: [-1, 1, false],\n headHalfWidth: [0, Infinity, true],\n};\n\n/** Every field `TurnTargets` has: a caller's names only these. */\nexport const TURN_TARGET_KEYS = Object.keys(RANGES) as (keyof TurnTargets)[];\n\n/** The shifts are magnitudes: `measure_turn_reference` signs them by the\n * reference's turn direction, and the rig turns both ways. */\nconst SHIFTS: ReadonlySet<keyof TurnTargets> = new Set([\n \"eyeShift\",\n \"noseShift\",\n \"mouthShift\",\n]);\n\nexport function checkedNumber(\n name: string,\n v: unknown,\n lo: number,\n hi: number,\n open = false,\n): number {\n if (typeof v !== \"number\" || !Number.isFinite(v)) {\n throw new TurnTargetError(\n `${name} must be a finite number, got ${String(v)}`,\n );\n }\n if ((open ? v <= lo : v < lo) || v > hi) {\n throw new TurnTargetError(\n `${name} ${v} is outside ${open ? \"(\" : \"[\"}${lo}, ${hi}]`,\n );\n }\n return v;\n}\n\n/** An options object a caller passed: absent, or a plain object naming only\n * the fields it has — a misspelt one would otherwise do nothing. */\nexport function checkedKeys(\n name: string,\n v: unknown,\n known: readonly string[],\n): void {\n if (v === undefined) return;\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n throw new TurnTargetError(`${name} must be a plain object`);\n }\n for (const key of Object.keys(v)) {\n if (!known.includes(key)) {\n throw new TurnTargetError(\n `${name}.${key} is not one of ${known.join(\", \")}`,\n );\n }\n }\n}\n\nexport function resolveTurnTargets(\n tt: TurnTargets | undefined,\n plateHalf: number,\n): ResolvedTargets {\n const out: ResolvedTargets = { given: new Set() };\n for (const key of TURN_TARGET_KEYS) {\n const v: unknown = tt?.[key];\n if (v === undefined) continue;\n const [lo, hi, open] = RANGES[key];\n const checked = checkedNumber(`turnTargets.${key}`, v, lo, hi, open);\n out[key] = SHIFTS.has(key) ? Math.abs(checked) : checked;\n if (key !== \"headHalfWidth\") out.given.add(key);\n }\n if (out.headHalfWidth !== undefined && out.headHalfWidth <= plateHalf) {\n throw new TurnTargetError(\n `turnTargets.headHalfWidth ${out.headHalfWidth} is not wider than the face plate (half-width ${plateHalf}): the silhouette would sit inside the face`,\n );\n }\n return out;\n}\n\n// --- cue geometry -----------------------------------------------------------\n\nexport interface IrisRow {\n role: string;\n /** Painted x-span on the iris's centre row, model. */\n lo: number;\n hi: number;\n y: number;\n}\n\nexport interface SolveContext {\n frame: HeadFrame;\n /** The iris (or, without irises, the eye) on the −x and the +x side. */\n left: IrisRow;\n right: IrisRow;\n /** Every role drawing the silhouette at the eye row, per side (boundary x). */\n candidates: {\n left: { role: string; x: number }[];\n right: { role: string; x: number }[];\n };\n /** Half that silhouette's rest span: what a render of the rig measures the\n * head as, and so what every shift cue is a fraction of. */\n restHalf: number;\n strand?: { left?: IrisStrand; right?: IrisStrand };\n hasHairFront: boolean;\n /** The eye whites on the −x and the +x side. */\n eyeBoxes: { left: Box; right: Box };\n noseAt?: { x: number; y: number };\n noseBox?: Box;\n mouthAt: { x: number; y: number };\n mouthBox: Box;\n}\n\n/** Landed x of a rest point on a role's part, at (AngleX `ax`, AngleY 0). */\nexport type Lander = (role: string, x: number, y: number, ax: number) => number;\n\n/** Lands through the family fields themselves: what the fit iterates on. */\nexport function analyticLander(m: TurnModel): Lander {\n const cache = new Map<Family, ReturnType<typeof familyField>>();\n return (role, x, y, ax) => {\n const family = roleSpec(role).family;\n let f = cache.get(family);\n if (f === undefined) {\n f = familyField(m, family);\n cache.set(family, f);\n }\n return x + f(x, y, ax, 0)[0];\n };\n}\n\ninterface Cues {\n eyeShift: number;\n farEyeRatio: number;\n silhouetteRatio: number;\n}\n\n/** The three cues `measure_turn_reference` reads, for a turn of `ax`. */\nfunction cuesAt(ctx: SolveContext, land: Lander, ax: number): Cues {\n const { left: L, right: R } = ctx;\n const l0 = land(L.role, L.lo, L.y, ax);\n const l1 = land(L.role, L.hi, L.y, ax);\n const r0 = land(R.role, R.lo, R.y, ax);\n const r1 = land(R.role, R.hi, R.y, ax);\n const wl = l1 - l0;\n const wr = r1 - r0;\n const wl0 = L.hi - L.lo;\n const wr0 = R.hi - R.lo;\n const ratio = ax < 0 ? wl / wr / (wl0 / wr0) : wr / wl / (wr0 / wl0);\n const pc0 = (L.lo + L.hi + R.lo + R.hi) / 4;\n const pc = (l0 + l1 + r0 + r1) / 4;\n const y = ctx.frame.eyeY;\n const hl0 = Math.min(...ctx.candidates.left.map((c) => c.x));\n const hr0 = Math.max(...ctx.candidates.right.map((c) => c.x));\n const hl = Math.min(\n ...ctx.candidates.left.map((c) => land(c.role, c.x, y, ax)),\n );\n const hr = Math.max(\n ...ctx.candidates.right.map((c) => land(c.role, c.x, y, ax)),\n );\n const half0 = ctx.restHalf;\n return {\n eyeShift: (pc - (hl + hr) / 2 - (pc0 - (hl0 + hr0) / 2)) / half0,\n farEyeRatio: ratio,\n silhouetteRatio: (hr - hl) / 2 / half0,\n };\n}\n\n/** Both turn directions, as magnitudes. */\nexport function meanCues(ctx: SolveContext, land: Lander): Cues {\n const a = cuesAt(ctx, land, -30);\n const b = cuesAt(ctx, land, 30);\n return {\n eyeShift: (Math.abs(a.eyeShift) + Math.abs(b.eyeShift)) / 2,\n farEyeRatio: (a.farEyeRatio + b.farEyeRatio) / 2,\n silhouetteRatio: (a.silhouetteRatio + b.silhouetteRatio) / 2,\n };\n}\n\n// --- strand coverage ----------------------------------------------------------\n\n/** How much of a far iris's painted row the bangs' run covers, px. */\nfunction coverage(\n strand: IrisStrand,\n side: -1 | 1,\n ctx: SolveContext,\n land: Lander,\n ax: number,\n): number {\n const iris = side < 0 ? ctx.left : ctx.right;\n const a = land(iris.role, strand.irisOuter, strand.y, ax);\n const b = land(iris.role, strand.irisInner, strand.y, ax);\n const ro = land(\"hair_front\", strand.runOuter, strand.y, ax);\n let lo: number;\n let hi: number;\n if (strand.runFace === null) {\n // A fringe spanning the face runs on inward without end.\n lo = side < 0 ? ro : -Infinity;\n hi = side < 0 ? Infinity : ro;\n } else {\n const rf = land(\"hair_front\", strand.runFace, strand.y, ax);\n lo = Math.min(ro, rf);\n hi = Math.max(ro, rf);\n }\n return Math.max(\n 0,\n Math.min(hi, Math.max(a, b)) - Math.max(lo, Math.min(a, b)),\n );\n}\n\n/** The side's far stops: the −x iris is the far one when turning toward −x. */\nconst farStops = (side: -1 | 1) => (side < 0 ? [-15, -30] : [15, 30]);\n\nexport function strandOverlaps(\n ctx: SolveContext,\n land: Lander,\n holdBase: number,\n): { left?: StrandOverlap; right?: StrandOverlap } | undefined {\n const out: { left?: StrandOverlap; right?: StrandOverlap } = {};\n for (const [key, side] of [\n [\"left\", -1],\n [\"right\", 1],\n ] as const) {\n const strand = ctx.strand?.[key];\n if (strand === undefined) continue;\n const restPx = coverage(strand, side, ctx, land, 0);\n let px = 0;\n let deg = farStops(side)[1];\n for (const ax of farStops(side)) {\n const c = coverage(strand, side, ctx, land, ax);\n if (c > px) {\n px = c;\n deg = ax;\n }\n }\n if (px <= 0) continue;\n out[key] = {\n deg,\n px: round3(px),\n hh: round3(px) / holdBase,\n restPx: round3(restPx),\n // A fringe spanning the face has no side to hold the iris clear of.\n held: strand.runFace !== null && px <= restPx + STRAND_SLACK,\n };\n }\n return out.left || out.right ? out : undefined;\n}\n\nconst round3 = (v: number) => Math.round(v * 1000) / 1000;\n\n/** Sub-pixel slack in \"no deeper under the strand than painted\". */\nconst STRAND_SLACK = 0.5;\n\n// --- the fit ----------------------------------------------------------------\n\n/** The knobs the fit turns (see `buildTurn`). */\nexport interface TurnParams {\n /** The whole turn's amount (1 = the profile). */\n turn: number;\n /** The features' lead over the plate (1 = the profile). */\n lead: number;\n /** The front hair's share of the plate's turn. */\n follow: number;\n /** Its outer edge's share (the head's outline where it draws it). */\n outline: number;\n /** The eyes' foreshortening per unit of turn (1 = the profile's, at the\n * profile's turn). */\n fore: number;\n /** The hair's width at full turn (the silhouette). */\n shell: number;\n /** A nose or mouth shift fitted or capped on its own, px. */\n nose?: number;\n mouth?: number;\n}\n\nexport type Build = (p: TurnParams) => TurnModel;\n\nexport interface TurnFit {\n model: TurnModel;\n clamped: (keyof TurnTargets)[];\n}\n\nfunction bisect(\n f: (v: number) => number,\n lo: number,\n hi: number,\n it = 50,\n): number {\n // f(lo) and f(hi) bracket 0 with f increasing.\n for (let i = 0; i < it; i++) {\n const mid = (lo + hi) / 2;\n if (f(mid) < 0) lo = mid;\n else hi = mid;\n }\n return (lo + hi) / 2;\n}\n\n/** The largest v in [0, hi] with ok(v), ok being true at 0 and monotone. */\nfunction largestOk(ok: (v: number) => boolean, hi: number): number {\n if (ok(hi)) return hi;\n let lo = 0;\n for (let i = 0; i < 40; i++) {\n const mid = (lo + hi) / 2;\n if (ok(mid)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\n\nconst fmt = (v: number) => v.toFixed(5);\n\n/** The most the turn and the foreshortening may be scaled while fitting. */\nconst TURN_MAX = 3;\nconst FORE_RANGE: [number, number] = [-1, 4];\nconst SHELL_RANGE: [number, number] = [0.8, 1.2];\n\nexport function fitTurn(\n ctx: SolveContext,\n targets: ResolvedTargets,\n style: ResolvedStyle,\n build: Build,\n): TurnFit {\n const clamped: (keyof TurnTargets)[] = [];\n // A given eyeShift fits the turn's amount, so the style's own amount has\n // no say: the fit starts from the profile, the eyes' foreshortening with it.\n const styleTurn = targets.eyeShift === undefined ? style.turn : 1;\n const p: TurnParams = {\n turn: styleTurn,\n lead: style.featureLead,\n follow: style.hairFollow,\n outline: style.outlineFollow,\n fore: 1,\n shell: 1,\n };\n const cues = (q: TurnParams) => meanCues(ctx, analyticLander(build(q)));\n\n // The turn's amount (eyeShift) and the eyes' foreshortening\n // (farEyeRatio): each cue leans a little on the other knob, so a few\n // rounds. The foreshortening is fitted as its product with the turn — the\n // eyes' own width change — so a small turn can still ask for it.\n let short = false;\n const fitTurnAmount = () => {\n if (targets.eyeShift === undefined) return;\n const e = targets.eyeShift;\n const g = p.fore * p.turn;\n const at = (turn: number) =>\n cues({ ...p, turn, fore: g / Math.max(turn, 1e-9) }).eyeShift;\n short = at(TURN_MAX) < e;\n const turn = short ? TURN_MAX : bisect((t) => at(t) - e, 1e-6, TURN_MAX);\n p.fore = g / turn;\n p.turn = turn;\n };\n const fitFore = () => {\n if (targets.farEyeRatio === undefined) return;\n const r = targets.farEyeRatio;\n const at = (g: number) =>\n cues({ ...p, fore: g / Math.max(p.turn, 1e-9) }).farEyeRatio;\n const hi = at(FORE_RANGE[0]);\n const lo = at(FORE_RANGE[1]);\n if (r > hi + 1e-9 || r < lo - 1e-9) {\n throw new TurnTargetError(\n `turnTargets.farEyeRatio ${r} is unreachable on this layer set: attainable ${fmt(lo)}…${fmt(hi)}`,\n );\n }\n p.fore =\n bisect((g) => r - at(g), FORE_RANGE[0], FORE_RANGE[1]) /\n Math.max(p.turn, 1e-9);\n };\n for (let i = 0; i < 3; i++) {\n fitTurnAmount();\n fitFore();\n }\n // The room: the far eye stays inside the plate, the chin over the neck it\n // slides across, and — best effort — the far iris clear of its strand. A\n // strand that leaves less than half the profile's own turn is left to\n // overlap (reported), not obeyed.\n const g = p.fore * p.turn;\n const withTurn = (turn: number) =>\n build({ ...p, turn, fore: g / Math.max(turn, 1e-9) });\n const plateTurn = largestOk(\n (turn) =>\n eyesInPlate(ctx, withTurn(turn)) && chinOverNeck(ctx, withTurn(turn)),\n p.turn,\n );\n const strandTurn = largestOk(\n (turn) => strandHeld(ctx, withTurn(turn)),\n p.turn,\n );\n let turn = Math.min(p.turn, plateTurn);\n if (strandTurn >= 0.5 * Math.min(p.turn, styleTurn))\n turn = Math.min(turn, strandTurn);\n if (turn < p.turn - 1e-6 || short) {\n p.fore = g / Math.max(turn, 1e-9);\n p.turn = turn;\n clamped.push(\"eyeShift\");\n }\n fitFore();\n\n // The hair's width at full turn.\n if (targets.silhouetteRatio !== undefined) {\n const s = targets.silhouetteRatio;\n const at = (shell: number) => cues({ ...p, shell }).silhouetteRatio;\n const lo = at(SHELL_RANGE[0]);\n const hi = at(SHELL_RANGE[1]);\n if (s < lo - 1e-9 || s > hi + 1e-9) {\n throw new TurnTargetError(\n `turnTargets.silhouetteRatio ${s} is unreachable on this layer set: attainable ${fmt(lo)}…${fmt(hi)}`,\n );\n }\n p.shell = bisect((k) => at(k) - s, SHELL_RANGE[0], SHELL_RANGE[1]);\n }\n // ... narrowing the plate (without hair) only as far as the head still\n // covers the far ear's slide on the line under it: its outer edge keeps\n // its lag, and its tucked strip stays under the head. A wider shell moves\n // that line further, so the least that covers it is found by halving.\n const covered = (shell: number) => farEarCovered(build({ ...p, shell }));\n if (!covered(p.shell) && covered(Math.max(1, p.shell))) {\n let lo = p.shell;\n let hi = Math.max(1, p.shell);\n for (let i = 0; i < 50; i++) {\n const mid = (lo + hi) / 2;\n if (covered(mid)) hi = mid;\n else lo = mid;\n }\n p.shell = hi;\n clamped.push(\"silhouetteRatio\");\n }\n\n // The nose and the mouth: each its own shift, inside the plate — as the\n // eye shift, a fraction of the head a render spans at the eye row.\n const hb = ctx.restHalf;\n const feature = (\n key: \"noseShift\" | \"mouthShift\",\n family: \"nose\" | \"mouth\",\n at: { x: number; y: number },\n box: Box,\n ) => {\n const base = build(p);\n const own = family === \"nose\" ? base.nose : base.mouth;\n const withPx = (px: number) => build({ ...p, [family]: px });\n const shiftOf = (px: number) => {\n const f = familyField(withPx(px), family);\n return (\n (Math.abs(f(at.x, at.y, -30, 0)[0]) +\n Math.abs(f(at.x, at.y, 30, 0)[0])) /\n 2 /\n hb\n );\n };\n // No slower than the plate under it, no further than its room.\n const floorPx = base.face;\n const ceilPx = largestOk(\n (px) => px <= floorPx || featureInPlate(ctx, withPx(px), family, box),\n Math.max(own, floorPx) * 3,\n );\n const asked = targets[key];\n if (asked !== undefined) {\n const lo = shiftOf(floorPx);\n const hi = shiftOf(Math.max(floorPx, ceilPx));\n if (asked < lo - 1e-6 || asked > hi + 1e-6) {\n throw new TurnTargetError(\n `turnTargets.${key} ${asked} is unreachable on this layer set: attainable ${fmt(lo)}…${fmt(hi)}`,\n );\n }\n p[family] = bisect(\n (px) => shiftOf(px) - asked,\n floorPx,\n Math.max(floorPx, ceilPx),\n );\n } else if (own > ceilPx) {\n p[family] = Math.max(floorPx, ceilPx);\n clamped.push(key);\n }\n };\n if (ctx.noseAt && ctx.noseBox) {\n feature(\"mouthShift\", \"mouth\", ctx.mouthAt, ctx.mouthBox);\n feature(\"noseShift\", \"nose\", ctx.noseAt, ctx.noseBox);\n }\n return { model: build(p), clamped };\n}\n\n// --- room -------------------------------------------------------------------\n\n/** A feature's far edge stays this fraction of its row's half-width inside\n * the plate's own far edge (the eyes: a pixel). */\nconst FEATURE_ROOM = 0.05;\nconst EYE_ROOM = 1;\n\nfunction plateEdge(\n ctx: SolveContext,\n land: Lander,\n y: number,\n side: -1 | 1,\n ax: number,\n): number {\n const w = ctx.frame.paintedHalfAt(y);\n return land(\"face\", ctx.frame.axisX + side * w, y, ax);\n}\n\n/** The far eye's far corner stays inside the plate's outline on its row —\n * unless a side strand frames that eye: the strand covers the outline\n * there, and the iris's own bound against it is what shows. */\nfunction eyesInPlate(ctx: SolveContext, m: TurnModel): boolean {\n const land = analyticLander(m);\n for (const [side, box, role, key] of [\n [-1, ctx.eyeBoxes.left, ctx.left.role, \"left\"],\n [1, ctx.eyeBoxes.right, ctx.right.role, \"right\"],\n ] as const) {\n const strand = ctx.strand?.[key];\n if (strand !== undefined && strand.runFace !== null) continue;\n const eyeRole = role.replace(/^iris_/, \"eye_\");\n const y = cy(box);\n const ax = 30 * side;\n const corner = land(eyeRole, side < 0 ? box.x0 : box.x1, y, ax);\n const edge = plateEdge(ctx, land, y, side, ax);\n const restIn =\n side *\n (ctx.frame.axisX +\n side * ctx.frame.paintedHalfAt(y) -\n (side < 0 ? box.x0 : box.x1));\n // An eye painted past the plate's outline may not go further past it.\n if (side * (edge - corner) < Math.min(EYE_ROOM, restIn)) return false;\n }\n return true;\n}\n\n/** The chin stays over the neck it slides across: past the neck's own\n * width, the neck's hidden top would come out from under the jaw. */\nfunction chinOverNeck(ctx: SolveContext, m: TurnModel): boolean {\n const { frame } = ctx;\n if (frame.neck === undefined) return true;\n return chinSlide(m) <= frame.neck.half;\n}\n\n/** The far iris goes no deeper under its bangs' strand than it is painted. */\nfunction strandHeld(ctx: SolveContext, m: TurnModel): boolean {\n const land = analyticLander(m);\n for (const [key, side] of [\n [\"left\", -1],\n [\"right\", 1],\n ] as const) {\n const strand = ctx.strand?.[key];\n if (strand === undefined || strand.runFace === null) continue;\n const rest = coverage(strand, side, ctx, land, 0);\n for (const ax of farStops(side)) {\n if (coverage(strand, side, ctx, land, ax) > rest + STRAND_SLACK)\n return false;\n }\n }\n return true;\n}\n\n/** A nose or mouth stays on the plate: its far edge keeps FEATURE_ROOM of its\n * row's half-width inside the plate's own far edge. */\nfunction featureInPlate(\n ctx: SolveContext,\n m: TurnModel,\n family: \"nose\" | \"mouth\",\n box: Box,\n): boolean {\n const land = analyticLander(m);\n const y = cy(box);\n const w = ctx.frame.paintedHalfAt(y);\n for (const side of [-1, 1] as const) {\n const ax = 30 * side;\n const far = land(family, side < 0 ? box.x0 : box.x1, y, ax);\n const edge = plateEdge(ctx, land, y, side, ax);\n if (side * (edge - far) < FEATURE_ROOM * w) return false;\n }\n return true;\n}\n\n// --- the report ---------------------------------------------------------------\n\nexport function turnReport(\n ctx: SolveContext,\n fit: TurnFit,\n rendered: Lander,\n): TurnSolveReport {\n const { frame } = ctx;\n const m = fit.model;\n const hb = frame.holdBase;\n const achieved = meanCues(ctx, rendered);\n // A shift at ±30 as the depth a rotation would need for it.\n const depth = (px: number) => px / Math.sin(Math.PI / 6);\n const eye = depth((m.eye.far + m.eye.near) / 2);\n const plate = depth(m.face);\n const w = frame.paintedHalfAt(frame.eyeY);\n const report: TurnSolveReport = {\n radius: round3((w * w) / (2 * Math.max(1e-3, eye - plate))),\n holdBase: hb,\n depths: {\n eye: round4(eye / hb),\n nose: round4(depth(m.nose) / hb),\n mouth: round4(depth(m.mouth) / hb),\n },\n achieved: {\n eyeShift: round4(achieved.eyeShift),\n farEyeRatio: round4(achieved.farEyeRatio),\n silhouetteRatio: round4(achieved.silhouetteRatio),\n },\n clamped: fit.clamped,\n };\n const overlap = strandOverlaps(ctx, rendered, hb);\n if (overlap !== undefined) report.strandOverlap = overlap;\n return report;\n}\n\nconst round4 = (v: number) => Math.round(v * 10000) / 10000;\n\n/** The turn model the knobs give: the profile, in this head's px. */\nexport function buildTurn(\n frame: HeadFrame,\n landmarks: Pick<\n TurnModel,\n \"boxes\" | \"noseAt\" | \"noseTopY\" | \"mouthAt\" | \"hairTop\" | \"hairFrontGrid\"\n >,\n q: TurnParams,\n): TurnModel {\n const hh = frame.hh;\n const A = q.turn;\n const face = A * hh * TURN.face;\n const lead = (v: number) => face + A * q.lead * hh * (v - TURN.face);\n // How far the far eye's outer corner goes: its shift, less its own\n // narrowing about its centre.\n const eyes = [landmarks.boxes.eye_L, landmarks.boxes.eye_R].filter(\n (e): e is NonNullable<typeof e> => e !== undefined,\n );\n const eyeHalf =\n eyes.reduce((sum, e) => sum + (e.x1 - e.x0) / 2, 0) /\n Math.max(1, eyes.length);\n const farScale = 1 + q.fore * A * (TURN.eyeFarScale - 1);\n const farCorner = lead(TURN.eyeFar) - (1 - farScale) * eyeHalf;\n return {\n frame,\n face,\n chinLead: A * q.lead * hh * TURN.chinLead,\n widthUpper: 1 + A * (TURN.widthUpper - 1),\n widthJaw: 1 + A * (TURN.widthJaw - 1),\n eye: { far: lead(TURN.eyeFar), near: lead(TURN.eyeNear) },\n // The eyes foreshorten as much as the head turns.\n eyeScale: {\n far: 1 + q.fore * A * (TURN.eyeFarScale - 1),\n near: 1 + q.fore * A * (TURN.eyeNearScale - 1),\n },\n brow: { far: lead(TURN.browFar), near: lead(TURN.browNear) },\n nose: q.nose ?? lead(TURN.nose),\n mouth: q.mouth ?? lead(TURN.mouth),\n mouthWidth: 1 + A * (TURN.mouthWidth - 1),\n tilt: A,\n hairFront: q.follow * face,\n hairFar: Math.max(q.follow * face, farCorner),\n hairOuter: q.outline * face,\n hairBack: A * hh * TURN.hairBack,\n shellScale: q.shell,\n earFarScale: 1 + A * (TURN.earFarScale - 1),\n ...landmarks,\n };\n}\n"],"mappings":"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","names":["import_format","deformers","y","x","span","x","import_format","import_format","P","import_format","import_format","import_format","P","P","P","s","e","import_format","rim","root","strand","P","xs","cols","rows","neck","b","top","land","g","turn","P"]}