feat(engine): asset sources for embedded + user theme dirs (Card theme phase 3)
Implements Phase 3 of CARD_PLAN.md — the embedded:// + themes:// asset
sources the card-theme system loads from. The bundled default-theme
manifest ships in the binary via Bevy's EmbeddedAssetRegistry; user
themes load from user_theme_dir() through a FileAssetReader-backed
source registered as `themes://`.
Registration is split across:
register_theme_asset_sources(&mut App)
Called BEFORE DefaultPlugins. Registers `themes://` while
AssetSourceBuilders is still mutable.
AssetSourcesPlugin
Added AFTER DefaultPlugins. Populates the EmbeddedAssetRegistry
that AssetPlugin's build step would otherwise overwrite.
Constants exposed for downstream consumers:
USER_THEMES = "themes" (asset-source name)
DEFAULT_THEME_MANIFEST_URL = "embedded://solitaire_engine/assets/themes/default/theme.ron"
Includes a stub default theme.ron (52 face slots + back) so
`ThemeManifest::validate()` accepts it today; PROVENANCE.md documents
the plan to drop in real SVG art (hayeah/playing-cards-assets) in a
follow-up.
4 new tests covering source registration, embedded-registry
population, manifest validation against the embedded stub, and the
manifest-URL constant matching the embedded asset path.
cargo check --workspace --all-targets / clippy --workspace
--all-targets -- -D warnings clean. cargo test could not be run in
this turn because the C linker (cc) is unexpectedly absent from the
sandbox; the test bodies compile cleanly under cargo check --tests
and will run on a normal toolchain.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# Default theme — provenance
|
||||
|
||||
This directory is the bundled-default card theme that ships embedded in
|
||||
the binary via Bevy's `embedded_asset!` macro (see
|
||||
`solitaire_engine/src/assets/sources.rs`). At runtime its files are
|
||||
addressable as `embedded://solitaire_engine/assets/themes/default/...`.
|
||||
|
||||
## Current state (Phase 3)
|
||||
|
||||
The `theme.ron` manifest in this directory lists all 52 face slots plus
|
||||
a back slot, but **the referenced SVG files do not yet exist**. The
|
||||
manifest is intentionally a stub so that:
|
||||
|
||||
1. `embedded_asset!` has a real file to bundle (the manifest itself).
|
||||
2. `ThemeManifest::validate` accepts the manifest (it requires all 52
|
||||
faces to be listed by name).
|
||||
3. The `embedded://` asset source can be source-registered and queried
|
||||
without runtime errors during Phase 3.
|
||||
|
||||
The actual SVG art will be added when the project swaps in the
|
||||
`hayeah/playing-cards-assets` artwork — see the implementation plan in
|
||||
`/CARD_PLAN.md`. At that point, every `.svg` filename listed in
|
||||
`theme.ron`'s `faces` map (and `back.svg`) must be added here, and each
|
||||
new file needs a corresponding `embedded_asset!(app, ...)` call in
|
||||
`solitaire_engine/src/assets/sources.rs::register_default_theme`.
|
||||
|
||||
## How to add files to the bundled default theme
|
||||
|
||||
For each new file you drop into this directory:
|
||||
|
||||
1. Drop the file under `solitaire_engine/assets/themes/default/`.
|
||||
2. Add one line to `register_default_theme` in
|
||||
`solitaire_engine/src/assets/sources.rs` of the form:
|
||||
```rust
|
||||
embedded_asset!(app, "../../assets/themes/default/<filename>");
|
||||
```
|
||||
(The path is relative to `sources.rs`, which lives in
|
||||
`solitaire_engine/src/assets/`.)
|
||||
3. Update this file with the licence and origin of the new asset.
|
||||
|
||||
## Licence
|
||||
|
||||
To be filled in once real artwork lands.
|
||||
@@ -0,0 +1,77 @@
|
||||
// Default card theme manifest — Phase 3 stub.
|
||||
//
|
||||
// The 53 SVG paths below are deliberate placeholders so the manifest
|
||||
// validates against `ThemeManifest::validate` (which requires all 52
|
||||
// faces plus a back). The actual SVG art lands in a later phase when
|
||||
// the swap to hayeah/playing-cards-assets is complete; until then this
|
||||
// file exists so the `embedded://` asset source has something to
|
||||
// register, and so source-registration tests have a real RON file to
|
||||
// parse.
|
||||
//
|
||||
// Suit / rank tokens follow `CardKey::manifest_name`:
|
||||
// suits: clubs, diamonds, hearts, spades
|
||||
// ranks: ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, jack, queen, king
|
||||
(
|
||||
meta: (
|
||||
id: "default",
|
||||
name: "Default",
|
||||
author: "Solitaire Quest",
|
||||
version: "0.1.0",
|
||||
card_aspect: (2, 3),
|
||||
),
|
||||
back: "back.svg",
|
||||
faces: {
|
||||
"clubs_ace": "clubs_ace.svg",
|
||||
"clubs_2": "clubs_2.svg",
|
||||
"clubs_3": "clubs_3.svg",
|
||||
"clubs_4": "clubs_4.svg",
|
||||
"clubs_5": "clubs_5.svg",
|
||||
"clubs_6": "clubs_6.svg",
|
||||
"clubs_7": "clubs_7.svg",
|
||||
"clubs_8": "clubs_8.svg",
|
||||
"clubs_9": "clubs_9.svg",
|
||||
"clubs_10": "clubs_10.svg",
|
||||
"clubs_jack": "clubs_jack.svg",
|
||||
"clubs_queen": "clubs_queen.svg",
|
||||
"clubs_king": "clubs_king.svg",
|
||||
"diamonds_ace": "diamonds_ace.svg",
|
||||
"diamonds_2": "diamonds_2.svg",
|
||||
"diamonds_3": "diamonds_3.svg",
|
||||
"diamonds_4": "diamonds_4.svg",
|
||||
"diamonds_5": "diamonds_5.svg",
|
||||
"diamonds_6": "diamonds_6.svg",
|
||||
"diamonds_7": "diamonds_7.svg",
|
||||
"diamonds_8": "diamonds_8.svg",
|
||||
"diamonds_9": "diamonds_9.svg",
|
||||
"diamonds_10": "diamonds_10.svg",
|
||||
"diamonds_jack": "diamonds_jack.svg",
|
||||
"diamonds_queen": "diamonds_queen.svg",
|
||||
"diamonds_king": "diamonds_king.svg",
|
||||
"hearts_ace": "hearts_ace.svg",
|
||||
"hearts_2": "hearts_2.svg",
|
||||
"hearts_3": "hearts_3.svg",
|
||||
"hearts_4": "hearts_4.svg",
|
||||
"hearts_5": "hearts_5.svg",
|
||||
"hearts_6": "hearts_6.svg",
|
||||
"hearts_7": "hearts_7.svg",
|
||||
"hearts_8": "hearts_8.svg",
|
||||
"hearts_9": "hearts_9.svg",
|
||||
"hearts_10": "hearts_10.svg",
|
||||
"hearts_jack": "hearts_jack.svg",
|
||||
"hearts_queen": "hearts_queen.svg",
|
||||
"hearts_king": "hearts_king.svg",
|
||||
"spades_ace": "spades_ace.svg",
|
||||
"spades_2": "spades_2.svg",
|
||||
"spades_3": "spades_3.svg",
|
||||
"spades_4": "spades_4.svg",
|
||||
"spades_5": "spades_5.svg",
|
||||
"spades_6": "spades_6.svg",
|
||||
"spades_7": "spades_7.svg",
|
||||
"spades_8": "spades_8.svg",
|
||||
"spades_9": "spades_9.svg",
|
||||
"spades_10": "spades_10.svg",
|
||||
"spades_jack": "spades_jack.svg",
|
||||
"spades_queen": "spades_queen.svg",
|
||||
"spades_king": "spades_king.svg",
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user