1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! **The support-surface class vocabulary** — the one closed token table in the placement stack.
//!
//! Lived in `placement::furnish` until the Stage-0b workspace split. It had to move: it is a token
//! table and four pure functions, `manifest::validate_manifest` validates against it, and `manifest`
//! is engine-free — so the vocabulary could not stay behind the Bevy boundary that `furnish` is.
//!
//! `site::kit` validates against this same table, which is the point: growing the vocabulary is one
//! row here, never a second list that can drift.
use Role;
use ManifestItem;
// Support-surface classes — the bitmask vocabulary that pairs a scatter prop with the *kind* of top it
// may rest on. A support piece `provides` the OR of the class bits for every token in its `surfaces`
// field (the *feature* axis — what a piece OFFERS — kept separate from `affordances`, the *service*
// axis, so a bed can afford "sleep" without doubling as a shelf); a scatter prop `requires` the bit for
// its `Role::Scatter { surface }` token, and rests only where `provides & requires != 0`. A typed
// support is a surface *feature*, not a generic shelf (Tutenel et al. 2010, "A Semantic Scene
// Description Language for Procedural Layout Solving", AIIDE; props attach to a specific support class in
// Infinigen Indoors, Raistrick et al. 2024, arXiv 2406.11824).
const SURFACE_SUPPORT: u32 = 1 << 0; // any support top (drawer/table/desk) — never a bed
const SURFACE_WORKTOP: u32 = 1 << 1; // a desk/table worktop only
// A narrow ledge inside a unit — a bookcase, a rack. Appended 2026-08-18 beside the `shelf` token in
// this game's `vocab.ron`: a bookcase and a desk both offer somewhere to put something, and what
// sits on one is not what sits on the other. Deliberately NOT implied by `support`: a piece that
// offers both says both, the way a desk already says `["support", "worktop"]`.
const SURFACE_SHELF: u32 = 1 << 2;
/// The whole surface-class vocabulary, token → class bit — THE single source of truth. [`surface_bits`]
/// resolves through this table and `manifest::validate_manifest` walks it to reject unknown tokens at
/// load, so growing the vocabulary is one row here — never a second list that can drift.
pub const SURFACE_CLASSES: & = &;
/// Map a support-surface token to its class bit. `support` = any support top; `worktop` = a desk/table.
/// An unrecognised token is `0` (matches nothing) — and `manifest::validate_manifest` rejects it at load
/// time, so a typo'd token errors at the door instead of silently dropping props at furnish time. Used
/// both for a support's provided classes and a scatter prop's required class.
/// The surface classes a support piece provides — the OR of [`surface_bits`] over its `surfaces` field
/// (a desk with `surfaces: ["support", "worktop"]` provides both; a bed with no `surfaces` provides
/// nothing, so no prop ever rests on it). Sourced from `surfaces`, NOT `affordances`: what a piece
/// OFFERS (the feature axis) is separate from what it is FOR (the service axis) — Tutenel et al. 2010.
/// The surface class a scatter prop requires, from its `Role::Scatter { surface }` token. A non-Scatter
/// role (never reached in Pass 4) requires nothing.