Commit Graph
115 Commits
Author SHA1 Message Date
hypercross d9d38c2bee fix(tabletop): key placements by surface, path, and piece
A piece can appear on more than one path of the same surface (e.g. the
poker deck expands to every card while the flop also places the ace), so
the render key must include the path to stay unique.
2026-08-09 22:46:06 +08:00
hypercross f494a6f9be feat(web): render bgm setups as a 3D table
Wire the tabletop library into the setup detail route: seed the store
from the setup, resolve the surface mount tree, and render world and HUD
surfaces. Add serializedToPackage to convert the vite-emitted package.
2026-08-09 22:46:03 +08:00
hypercross cd08e6af04 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.
2026-08-09 22:34:18 +08:00
hypercross ef0695ed04 refactor: update file paths in poker documentation
Remove the `parts/` and `setup/` prefixes from file references in
`games/poker/poker.md` to match the updated file structure.
2026-08-09 22:22:43 +08:00
hypercross 15c45e7106 refactor: share trace, error boundary, and proxy http helpers
Lift the trace-to-shape geometry into @tts/mesh (traceToShape/
traceToUvBounds), parameterized by scale so the web token viewer and
@tts/tabletop share one implementation. Move the CORS proxy HTTP helpers
(assetUrl, resolveAssetUrl, traceImage) into a new @tts/http package, and
make @tts/tabletop's ErrorBoundary the single source used by the web app.

This removes the duplicated ErrorBoundary, assetUrl, tabletopHttp, and
trace-to-shape code from apps/web and packages/tabletop.
2026-08-09 22:17:24 +08:00
hypercross b4cdcdeb42 fix(bgm): pass options arg to buildStart in unit test
Vite 8 (rolldown) changed buildStart to take (this, options), so the
test's one-arg call failed typecheck. Add an ambient declaration for the
fixture's virtual bgm modules so its entry typechecks in the editor.
2026-08-09 22:17:19 +08:00
hypercross 87e6eee9fe docs: update bgm loader status 2026-08-09 21:48:46 +08:00
hypercross 521519ce3d feat(tabletop): inject proxy handlers from web app 2026-08-09 21:46:36 +08:00
hypercross eefce5487d feat(poker): add card assets and wire them up 2026-08-09 21:46:30 +08:00
hypercross 4d14120d54 fix(proxy): wire games root into asset routes 2026-08-09 21:44:07 +08:00
hypercross 91d4b6c999 feat(proxy): serve local game assets from games root 2026-08-09 21:31:23 +08:00
hypercross 0503ac84a7 feat(bgm): resolve relative part assets against source dir 2026-08-09 21:19:37 +08:00
hypercross 43b69133cc docs: add bgm-tabletop implementation plan 2026-08-09 21:08:01 +08:00
hypercross 599fb6a76d feat(bgm): add surface mounting and setup surfaces 2026-08-09 21:03:20 +08:00
hypercross 4e18ab5bc8 feat(web): add bgm viewer navigation 2026-08-09 20:02:03 +08:00
hypercross 64c8bb60b3 feat(web): add bgm package browser 2026-08-09 19:44:27 +08:00
hypercross c86d7444b8 docs: add poker game document 2026-08-09 19:44:05 +08:00
hypercross 7f3f758c52 test(bgm): cover emitted shape and multi-package collection
Add a SerializedPackage type for the JSON the plugin emits, and tests
that assert the maps serialize to plain objects, that the packages module
returns every package, and that buildStart watches def files. Add a
second fixture package to exercise multi-package collection.
2026-08-09 19:23:50 +08:00
hypercross 845d510948 refactor(bgm): use virtual: module specifiers
Rename the plugin's virtual modules to virtual:bgm/packages and
virtual:bgm/package/<id> so they read as plugin-provided modules rather
than real packages. Update the unit and build integration tests.
2026-08-09 19:16:17 +08:00
hypercross ba16f17d8a feat(bgm): add vite plugin and build integration test
Move the bgm vite plugin into the package so it can be tested in
isolation from the web app. Serve each package as a JSON module,
serializing its maps, and verify resolution through a real vite build
against a self-contained fixture.
2026-08-09 19:07:14 +08:00
hypercross c0967ab71f feat(bgm): add board game manifest loader
Parse yaml/json/toml and markdown code blocks into packages, expanding
$variants via typed-csv and collecting parts, surfaces, and setups by
include patterns. Ships zod validation, a vitest config, and 16 tests.
2026-08-09 18:59:14 +08:00
hypercross 1cfec40c99 docs: simplify BGM format description 2026-08-09 18:17:47 +08:00
hypercross 664079528c docs: add board game manifest specification 2026-08-09 18:14:43 +08:00
hypercross 82a81c9c1a feat(web): tint objects by their ColorDiffuse
Model ColorDiffuse in shared types and multiply each viewer's material color by the per-object tint, including textured faces and loaded custom models.
2026-08-08 22:38:12 +08:00
hypercross a6e9d2dd07 fix(web): correct transform rotation and lay-flat sign
Conjugate the rotation by the Z-reflection (negate rotX/rotY, keep rotZ) and use -90 degrees about X to lay extruded meshes flat so faces point up.
2026-08-08 20:19:13 +08:00
hypercross dcba0ac4bd feat(web): place full setup objects at their real transforms
Model TTSObjectTransform in shared types and convert each object's position, rotation, and scale into three.js placement, with per-class base-size corrections and a lay-flat rotation for extruded meshes.
2026-08-08 18:41:42 +08:00
hypercross c3c7fe2445 feat(web): show asset loading progress in the 3D scene 2026-08-08 18:41:41 +08:00
hypercross c04d99fe38 docs: document object viewers and asset proxy 2026-08-08 18:28:56 +08:00
hypercross e88dd03fac feat(web): add full setup view rendering the whole save
Add a /mod/:id/setup page that lays out every renderable object in a single shared scene. Export object-facing mesh wrappers from the viewers and share geometry and materials across objects via module-level caches.
2026-08-08 18:28:03 +08:00
hypercross 12418898d0 docs: update mesh, viewers, and selection decisions
Document the separated front/back/walls extrusion, material-level back
flips, CardID sprite selection from the parent deck, index-path tree
selection, and the Bounds-inside-Suspense camera fit.
2026-08-08 18:18:22 +08:00
hypercross ead2ba8c57 fix(web): improve scene camera and bounds behavior
Update Bounds props to enable fitting and clipping, adjust OrbitControls
minDistance, and set makeDefault to ensure proper interaction.
2026-08-08 18:16:03 +08:00
hypercross b6bd4612e0 feat: implement suspense-based alpha tracing for token meshes
Refactor `TokenMesh` to use a custom `useTrace` hook that suspends
during the alpha channel tracing process. This allows the `Bounds`
component in `Scene` to correctly fit the camera to the token's
geometry once it has been fully loaded and traced.
2026-08-08 17:54:43 +08:00
hypercross 55e0351c1d fix(web): select tree nodes by index path instead of GUID
Cards in a deck share the deck's GUID, so GUID-based selection highlighted
every card with that GUID and rendered the first match. Key selection by the
node's unique index path instead.
2026-08-08 17:42:16 +08:00
hypercross 835250abdd feat(mesh): render cards, tiles, and tokens with separated front/back/walls
Split extrudeShapeParts into front, back, and walls so each face can carry
its own material. Flip back textures left/right on the material so they are
not mirrored, and slice card faces from the deck sprite sheet via CardID.
Resolve deck config from the parent deck, which is authoritative over a
card's own CustomDeck. Add unit tests for card resolution, sprite UVs, and
the flip helper.
2026-08-08 17:41:59 +08:00
hypercross f7139495fe fix(proxy): load clipper-lib via require in ESM
The compiled server runs Node's native ESM loader, where the CommonJS
namespace object nests the real exports under 'default', so
'import * as ClipperLib' left JoinType undefined and crashed with
offset. Match the existing vtracer pattern and require() the package
instead.
2026-08-08 15:40:32 +08:00
hypercross a2f7c998fc feat(web): inset token silhouette by 2px
Pass a negative offset through traceImage so the traced token shape
sits slightly inside the artwork, hiding the anti-aliased fringe.
2026-08-08 15:37:32 +08:00
hypercross 9094ad58e0 feat(proxy): add offset param to inset or outset traced shapes
Trace results can now be inset (negative) or outset (positive) by a
pixel amount. Offset the outline and holes in opposite directions with
clipper-lib's miter joins, then recombine with a boolean difference so
holes grow on inset and shrink on outset. Collapsed shapes return an
empty outline; a split outline keeps the largest ring. Document the
parameter and the new dependency.
2026-08-08 15:37:27 +08:00
hypercross c7f4bd03fd docs: document mesh package and traced token viewer 2026-08-08 15:12:15 +08:00
hypercross a4759be5ac feat(web): trace token shape and texture the whole mesh
TokenViewer now traces the image's alpha channel via /trace and extrudes the silhouette with @tts/mesh, aligning the texture using the full image as the UV framing. The texture is applied to the whole mesh (top, back, and walls) instead of separate solid-white walls.
2026-08-08 15:12:11 +08:00
hypercross 21fc1b29c1 feat(mesh): support uvBounds and planar back-face UVs
Add an optional uvBounds to extrudeShape/extrudeShapeParts so UVs can be derived from a framing rectangle instead of the shape's bounding box, letting a traced silhouette align with its full image. The bottom face now uses the same planar xy UVs as the top face (no horizontal mirror), so the texture is consistent across front, back, and walls.
2026-08-08 15:12:07 +08:00
hypercross dc8127dba1 docs: document image tracing endpoint 2026-08-08 14:51:40 +08:00
hypercross 445dbc1781 feat(proxy): add image tracing endpoint
Add GET /trace which fetches an image, traces it into a vector shape, and returns the result BSON-encoded. Tracing is configurable via mode (alpha, bw, color) and format (shape, svg). The shape format parses the vtracer SVG into an outline/holes polygon matching @tts/mesh's Shape interface.
2026-08-08 14:51:36 +08:00
hypercross d554d6bde1 feat(tile): render tiles with the mesh generator
Replace the per-shape tile geometries with @tts/mesh extrusion, honoring
the tile type and stretch aspect ratio. Add extrudeShapeParts so the
caps carry the texture while the walls are solid white, matching TTS
tinting. Fix bottom-face UVs to mirror horizontally and make wall UVs
inherit the front mapping independent of z.
2026-08-08 14:21:53 +08:00
hypercross 14f83f476c feat(mesh): add tile mesh generation package
Add @tts/mesh, a package for generating extruded tile meshes from 2D
shapes. It provides shape generators (rect, hex, circle, rounded rect,
frame), earcut-based tessellation of top/bottom faces with UVs, and
outward-normal wall generation, combined into raw BufferGeometry-ready
typed arrays.
2026-08-08 13:42:32 +08:00
hypercross 3b86a641aa Fix custom model loading and hook order
Detect the model format from file contents instead of the URL extension,
since TTS model URLs are often extension-less. Move the diffuse texture
hook into a child component so the hook count stays consistent across
renders.
2026-08-08 13:06:01 +08:00
hypercross 179efae99f Fix R3F hooks used outside the Canvas
Move useTexture calls in the tile, token, and card viewers into child
components rendered inside the Canvas. R3F hooks must run within the
Canvas store, so calling them at the viewer's top level threw a runtime
error.
2026-08-08 12:59:32 +08:00
hypercross 7d1f05902d Add error boundary around object viewers
Wrap the resolved viewer in an error boundary so a render failure (e.g.
WebGL context loss or a model/texture load error) is contained to the
inspector pane instead of crashing the page. The fallback shows the
error message and stack trace.
2026-08-08 12:58:28 +08:00
hypercross 001d5eeb54 Add 3D object viewers with r3f stack
Add per-class 3D viewers for tiles, tokens, cards, and custom models
using React Three Fiber, drei, and postprocessing. Viewers are
lazy-loaded and registered through the existing viewer registry, with a
shared scene wrapper for lighting, orbit controls, and subtle effects.

Add a CORS-safe /asset proxy route so three.js loaders can fetch
Workshop-hosted textures and models, and extend TTSObject with the
CustomMesh and CustomTile/CustomToken fields the viewers read.
2026-08-08 12:56:46 +08:00
hypercross f390f170da docs: clarify multi-set and CDN-loaded object icons 2026-08-08 12:47:05 +08:00
hypercross 9619cc3863 feat(web): expand object class icon mapping
Map more TTS classes to icons, including multi-set icons for models and
bags, and add a wrap-break-word class fix in the default viewer.
2026-08-08 12:45:40 +08:00