import { Group, Object3D, Vector3 } from 'three'; /** * Deterministic seeded randomness — the backbone of SCENA. Same seed, * same tree; forests are reproducible, diffable and network-syncable. */ declare class Rng { private state; constructor(seed?: number); /** Next float in [0, 1) (mulberry32). */ next(): number; /** Float in [min, max). */ range(min: number, max: number): number; /** Integer in [min, max] inclusive. */ int(min: number, max: number): number; /** Random element of a non-empty array. */ pick(items: readonly T[]): T; /** value ± spread (uniform). */ jitter(value: number, spread: number): number; /** A new independent Rng derived from this one. */ fork(): Rng; } /** Integer-lattice hash to [0, 1) — the base of the value noise. */ declare function hash2(ix: number, iz: number, seed: number): number; /** 2D value noise in [0, 1). Continuous; used by terrain and scatter density. */ declare function valueNoise2(x: number, z: number, seed: number): number; /** Fractal (octaved) value noise in [0, 1). */ declare function fractalNoise2(x: number, z: number, seed: number, octaves?: number, lacunarity?: number, gain?: number): number; /** * Theme palettes: one coherent set of colors shared by every generator, * so procedural props look like a matched set rather than a junk drawer. * Pass `palette` to any generator to restyle it; whole scenes retheme by * building with a different palette. */ interface Palette { foliage: number[]; trunk: number; rock: number[]; wood: number; woodDark: number; metal: number; lampGlow: number; grassLow: number; grassHigh: number; cliff: number; peak: number; skyTop: number; skyBottom: number; fog: number; water: number; sand: number; path: number; /** Building plaster/wall color. */ wall: number; /** Building roof color. */ roof: number; } declare const PALETTES: Record<'meadow' | 'autumn' | 'dusk' | 'winter' | 'urban', Palette>; declare const DEFAULT_PALETTE: Palette; /** * A steering obstacle in world space — structurally identical to GAMA's * `Obstacle`, so SCENA props plug straight into `ObstacleAvoidance` * without either library importing the other. */ interface Obstacle { center: Vector3; radius: number; } /** * An interaction slot — where and how a character uses this prop. * Structurally identical to ANIMA's `InteractionSlot` (anchor at floor * level, +z the facing direction, pitched for lying poses), so a prop's * slot drops straight into `new Interaction(rig, loco).use(slot)` without * either library importing the other. */ interface PropSlot { /** Free label: 'sit', 'sleep', 'driver', 'run'… */ kind: string; /** The transform target for the character's root (a child of the prop). */ anchor: Object3D; /** ANIMA pose name ('sit', 'sleep', 'drive', 'cycle', …) or 'run'. */ pose: string; /** Optional arms loop ('strum', 'hammer', 'knead'). */ loop?: string; /** * Where a character should *stand* before taking the slot — beside the * chair, not on it. Nobody materialises into a seat: they walk here, turn, * then lower. ANIMA's `Interaction.use(slot, { approach: true })` reads it * to stage the sit; steering agents path to it rather than to the anchor. */ approach?: Object3D; } /** How a character holds a carryable — structurally ANIMA's `CarryStyle`. */ type CarryStyle = 'crate' | 'tray' | 'shoulder' | 'side'; /** * A prop a character can pick up and carry. Structurally identical to ANIMA's * `Holdable`, so a SCENA crate drops into `new Carry(rig, loco).pickUp(crate)` * with no cross-imports. The object's origin stays at its base (natural for * ground placement); `grip` offsets the *hold point* — where it rides in the * hands — from that origin. */ interface Carryable extends Prop { /** The carry pose the holder adopts. */ carry: CarryStyle; /** Hold-point offset from the object's origin (metres). */ grip?: { x?: number; y?: number; z?: number; }; } /** * A flat surface on a prop that things can be put down on: a tabletop, a * shelf board, the lid of a chest, a windowsill. * * The anchor sits **on** the surface with +y up, +x along its width and +z * along its depth, so `dress` only has to think in two dimensions and the * height of whatever it places. */ interface PropSurface { /** Free label: 'top', 'shelf', 'sill'. */ kind: string; /** Anchor at surface level, a child of the prop. */ anchor: Object3D; /** Usable extent along the anchor's local x and z, in metres. */ width: number; depth: number; } /** * A body of water something can be in, in **world** coordinates. * * The swimming handshake, and it mirrors `terrain.heightAt` and * `ocean.heightAt`: the prop answers questions about the water and ANIMA * decides what a body does about it. `depthAt` returns 0 anywhere outside, * so "am I in the water" needs no separate `contains`. * * The interesting number is the **depth**, not the surface. Whether a * character wades or swims is a decision made against their own height, and * a pool with one depth everywhere cannot pose that question at all. */ interface WaterBody { /** World Y of the still surface. */ readonly surfaceY: number; /** Water depth at a world point, in metres. 0 anywhere outside. */ depthAt(x: number, z: number): number; /** Ripple it at a world point — a stroke, a dive, a hand going in. */ disturb(x: number, z: number, strength?: number): void; } /** What a prop generator returns: the visual plus gameplay metadata. */ interface Prop { object: Group; /** * Footprint radius for steering/placement, in the prop's local space * (centered at its origin). 0 means walk-through (e.g. grass). */ obstacleRadius: number; /** Interaction slots, on props a character can use. */ slots?: PropSlot[]; /** Flat surfaces things can be set down on — feed these to `dress`. */ surfaces?: PropSurface[]; /** * Which way up this comes to rest when it is set down on something. * * Props are authored in the orientation they are *used* in, which for a * phone is upright in a hand — put one down as authored and it stands on * its short edge like a domino. `dress` works this out for itself from the * shape (a slab lies down, a candle does not); set this only to override. */ rest?: 'upright' | 'flat'; } /** Build a surface: an anchor parented into the prop at (x, y, z). */ declare function createPropSurface(kind: string, parent: Group, x: number, y: number, z: number, width: number, depth: number, rotY?: number): PropSurface; /** * A prop several characters use *together* — a dining table, a bench, a * game board. Beyond the seats it publishes a **focus**: the thing the * occupants attend to. Point every sitter's gaze at it and a row of bodies * becomes a group; without it they are strangers who happen to be adjacent. */ interface Gathering extends Prop { /** The places, in a stable order — index 0 is the head of the table. */ seats: PropSlot[]; /** What the occupants look at: table centre, game board, campfire. */ focus: Object3D; } /** Build a slot: an anchor Object3D parented into the prop at (x, y, z). */ declare function createSlot(kind: string, pose: string, parent: Group, x: number, y: number, z: number, rotY?: number, rotX?: number): PropSlot; /** * Give a slot its standing-room-before: an approach anchor `distance` metres * from the seat, facing the same way. The character walks here, turns, and * lowers backwards into the slot — which is how sitting actually works. * * `from` picks the side the character comes at it from, and it must be the * side that is *open*. A dining chair is approached from behind (the table * is in front of it); a park bench is approached from the front (the * backrest is behind it). Get this backwards and characters walk through * the furniture to reach their seats. */ declare function addApproach(slot: PropSlot, parent: Group, distance?: number, from?: 'behind' | 'front'): PropSlot; /** Collect world-space obstacles from placed props (call after positioning). */ declare function collectObstacles(props: Iterable): Obstacle[]; export { type CarryStyle as C, DEFAULT_PALETTE as D, type Gathering as G, type Obstacle as O, PALETTES as P, Rng as R, type WaterBody as W, type Carryable as a, type Palette as b, type Prop as c, type PropSlot as d, type PropSurface as e, addApproach as f, collectObstacles as g, createPropSurface as h, createSlot as i, fractalNoise2 as j, hash2 as k, valueNoise2 as v };