Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
b6dddf934This file is pinned to the selected release. Download the original to open it in your design tool.
/**
* An individual's plates, drawn with the generated copies of the shader and the models
* (daemons/README.md "Individual art"; `plates/*.g.ts`, written by daemons/tools/generate.mjs).
*
* The unit is one size and one version: every mood's loop, all of them sharing one crop, exactly as
* `bakeModel` crops a species plate (so nothing jumps when the mood changes). It IS `bakeModel`, given
* the roster's rules narrowed to that size and version: the crop is per size and version there too, so
* the frames are the ones a whole-individual bake gives, byte for byte.
*
* This is CPU work measured in seconds (a reveal frame of a busy model takes most of one), so harnessd
* runs it in a worker thread (pair/plateWorker.ts); nothing here touches the event loop's I/O.
*/
import { bakeModel } from './plates/plate.g.js'
import { rollTraits } from './plates/render.g.js'
import { PLATE_MODELS, PLATE_ROSTER, PLATE_SOURCE } from './plates/models.g.js'
export type PlateSize = 'portrait' | 'reveal'
/** One frame: its rows, and each cell's material (`m` marking, `a` extra, `e` odd eye, `.` the body). */
export interface PlateFrame { rows: string; mats: string }
/** Every mood's loop at one size and version: `{ idle: [8 frames], work: [4], … }`. */
export type PlateUnit = Record<string, PlateFrame[]>
export interface PlateJob { id: string; seed: number; size: PlateSize; version: string }
type Rules = typeof PLATE_ROSTER.rules
type Model = (inputs: { t: number; mood: string; age: string; traits: unknown }) => unknown
/** What the plates were drawn from: a cache entry from another source is drawn again. */
export const plateSource = (): string => PLATE_SOURCE
export const plateRules = (): Rules => PLATE_ROSTER.rules
/** A species harnessd can draw (it has a model). */
export function hasPlateModel(id: string): boolean {
return Object.prototype.hasOwnProperty.call(PLATE_MODELS, id)
}
export function renderPlateUnit(job: PlateJob): PlateUnit {
if (!hasPlateModel(job.id)) throw new Error(`no model for ${job.id}`)
const rules = PLATE_ROSTER.rules
const cols = rules.plate.cols[job.size]
if (!cols || !(rules.versions as readonly string[]).includes(job.version)) throw new Error(`no ${job.size} ${job.version} plate`)
const model = (PLATE_MODELS as unknown as Record<string, { model: Model }>)[job.id].model
const traits = rollTraits(PLATE_ROSTER, job.id, job.seed)
const narrowed = { ...rules, versions: [job.version], plate: { ...rules.plate, cols: { [job.size]: cols } } }
const baked = bakeModel(model, narrowed, { traits, mats: true }) as Record<string, Record<string, PlateUnit>>
return baked[job.size][job.version]
}