feat(tabletop): add state, setup, mounting, and stacking
Implement the tabletop library's game state store, setup seeding with bare-type expansion, surface mount tree resolution, part placement, and the stacking positioning process with a dependency-free SVG path helper. Wire the public API and add unit plus vite integration tests.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* `PartPlacement` — position a part on a surface location.
|
||||
*
|
||||
* A stable per-part component that places a part at its route's anchor (plus
|
||||
* the candidate's anchor when there is one) and applies the route's stacking
|
||||
* strategy via `useStacking`. Renders the part's mesh with `PartView`.
|
||||
*/
|
||||
import type { Package } from '@tts/bgm';
|
||||
import { useStacking } from './stacking.js';
|
||||
import type { Placement } from './state.js';
|
||||
import { PartView } from './partView.js';
|
||||
|
||||
export function PartPlacement({ pkg, placement }: { pkg: Package; placement: Placement }) {
|
||||
const { route, candidate, piece, index, stackSize } = placement;
|
||||
// `piece` is `package:type#id`; the parts map is keyed by `type#id`.
|
||||
const part = pkg.parts.get(piece.split(':').slice(1).join(':'));
|
||||
if (!part) return null;
|
||||
|
||||
const { x, y, rotation } = useStacking(route.stacking, index, stackSize);
|
||||
|
||||
const anchorX = (candidate?.x ?? route.x ?? 0) + x;
|
||||
const anchorY = (candidate?.y ?? route.y ?? 0) + y;
|
||||
const anchorRotation = (candidate?.rotation ?? route.rotation ?? 0) + rotation;
|
||||
|
||||
return (
|
||||
<group position={[anchorX, 0, anchorY]} rotation={[0, anchorRotation, 0]}>
|
||||
<PartView part={part} baseUrl={part.baseUrl} />
|
||||
</group>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user