Skip to content

Commit

Permalink
feat: add system params for iterating over asset packs (#482)
Browse files Browse the repository at this point in the history
Closes #272

## Changes

- Add system param `Packs` -- an iterator over asset pack roots
    - Directly addresses #272
- Add system param `AllPacksData` -- a flattened, chained iterator over
listwise data from core and supplementary asset packs
- `AllPacksData::iter_with` takes 2 args: (1) a closure that takes a ref
to the core meta and returns an iterator, (2) a closure takes a ref to a
(supplementary) pack meta and returns an iterator

## Application

`AllPacksData` will be most the most useful of the 2 in Jumpy. There are
a few locations where we iterate over
a list from the core meta and do something, then we iterate over the
packs and for each one iterate over a list. Since `AllPacksData` is a
flattened, chained iterator of all of those sub-iterators, we can turn
this:

```rust
fn maps_sys(asset_server: Res<AssetServer>, game: Root<GameMeta>) {
    for handle in game.core.stable_maps.iter().copied() {
        let map_meta = asset_server.get(handle);
        /* do stuff... */
    }

    for pack in asset_server.packs() {
        let pack_meta = asset_server.get(pack.root.typed::<PackMeta>());
        for handle in pack_meta.maps.iter().copied() {
            let map_meta = asset_server.get(handle);
            /* do stuff... */
        }
    }
}
```

Into this:

```rust
fn maps_sys(asset_server: Res<AssetServer>, all_packs: AllPacksData<GameMeta, PackMeta>) {
    for handle in all_packs.iter_with(
    	|game| game.core.stable_maps.iter().copied(),
    	|pack| pack.maps.iter().copied(),
    ) {
        let map_meta = asset_server.get(handle);
        /* do stuff... */
    }
}
```
  • Loading branch information
nelson137 authored Oct 11, 2024
1 parent 016ed7e commit 560c259
Show file tree
Hide file tree
Showing 17 changed files with 549 additions and 2 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions demos/asset_packs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "demo_asset_packs"
edition.workspace = true
version.workspace = true
license.workspace = true
publish = false

[dependencies]
bones_framework = { path = "../../framework_crates/bones_framework" }
bones_bevy_renderer = { path = "../../framework_crates/bones_bevy_renderer" }
4 changes: 4 additions & 0 deletions demos/asset_packs/assets/game.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This is our root asset file, which corresponds to our `GameMeta` struct.

title: Asset Packs
core_items: [1, 2, 3]
4 changes: 4 additions & 0 deletions demos/asset_packs/assets/pack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This is the core asset pack file. It's only job is to specify
# the path to the root asset.

root: ./game.yaml
3 changes: 3 additions & 0 deletions demos/asset_packs/packs/pack1/data.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This is our root asset file, which corresponds to our `PackMeta` struct.

items: [10, 11, 12]
9 changes: 9 additions & 0 deletions demos/asset_packs/packs/pack1/pack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This is the core asset pack file. It's only job is to specify
# the path to the root asset.

name: Pack 1
id: pack1_01J9GBGEDY07CT16AQYPKJRKCY
version: 0.1.0
game_version: 0.1.0
root: ./data.yaml
schemas: []
3 changes: 3 additions & 0 deletions demos/asset_packs/packs/pack2/data.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This is our root asset file, which corresponds to our `PackMeta` struct.

items: [21, 22, 23]
9 changes: 9 additions & 0 deletions demos/asset_packs/packs/pack2/pack.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This is the core asset pack file. It's only job is to specify
# the path to the root asset.

name: Pack 2
id: pack2_01J9GBGEDYEAX5DMWGNJM9356T
version: 0.1.0
game_version: 0.1.0
root: ./data.yaml
schemas: []
86 changes: 86 additions & 0 deletions demos/asset_packs/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use bones_bevy_renderer::BonesBevyRenderer;
use bones_framework::prelude::*;

//
// NOTE: You must run this example from within the `demos/asset_packs` folder. Also, be sure to
// look at the `assets/` and `packs/` folders to see the asset files for this example.
//

/// Our "core" asset type.
#[derive(HasSchema, Clone, Default)]
#[repr(C)]
// We must mark this as a metadata asset, and we set the type to "game".
//
// This means that any files with names like `game.yaml`, `game.yml`, `game.json`, `name.game.yaml`,
// etc. will be loaded as a `GameMeta` asset.
#[type_data(metadata_asset("game"))]
struct GameMeta {
title: String,
core_items: SVec<i32>,
}

/// Our "supplementary" asset type.
#[derive(HasSchema, Clone, Default)]
#[repr(C)]
#[type_data(metadata_asset("data"))]
struct PackMeta {
items: SVec<i32>,
}

fn main() {
// Setup logging
setup_logs!();

// First create bones game.
let mut game = Game::new();

game
// We initialize the asset server.
.init_shared_resource::<AssetServer>();

// We must register all of our asset types before they can be loaded by the asset server. This
// may be done by calling schema() on each of our types, to register them with the schema
// registry.
GameMeta::register_schema();
PackMeta::register_schema();

// Create a new session for the game menu. Each session is it's own bones world with it's own
// plugins, systems, and entities.
let menu_session = game.sessions.create("menu");
menu_session
// Install the default bones_framework plugin for this session
.install_plugin(DefaultSessionPlugin)
// Add our menu system to the update stage
.add_system_to_stage(Update, menu_system);

BonesBevyRenderer::new(game).app().run();
}

/// System to render the home menu.
fn menu_system(
egui_ctx: Res<EguiCtx>,
core_meta: Root<GameMeta>,
all_packs: AllPacksData<GameMeta, PackMeta>,
) {
egui::CentralPanel::default()
.frame(egui::Frame::none().outer_margin(egui::Margin::same(32.0)))
.show(&egui_ctx, |ui| {
// Use the title that has been loaded from the asset
ui.heading(&core_meta.title);

ui.separator();

ui.label(egui::RichText::new("Items from all asset packs:"));

// Show the numbers from all of the asset packs
egui::Grid::new("pack-items").num_columns(1).show(ui, |ui| {
for item in all_packs.iter_with(
|core| core.core_items.iter().copied(),
|pack| pack.items.iter().copied(),
) {
ui.label(item.to_string());
ui.end_row();
}
});
});
}
Loading

0 comments on commit 560c259

Please sign in to comment.