Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support vectors of dynamic assets in dynamic asset files #151

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

- Support collections of dynamic assets in dynamic asset files (resolves [#78](https://github.com/NiklasEi/bevy_asset_loader/issues/78))
- Remove `Files` in preference of collections of `File`
- Previously:
```ron
({
"images": Files (
paths: ["images/tree.png", "images/player.png"],
)
})
```
- Now:
```ron
({
"images": [
File(path: "images/tree.png"),
File(path: "images/player.png")
]
})
```

## v0.17.0
- update to Bevy 0.11
- Use "/" in paths used as keys for mapped collections on all platforms (resolves [#135](https://github.com/NiklasEi/bevy_asset_loader/issues/135))
Expand Down
24 changes: 10 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ The following sections describe more types of asset fields that you can load thr

#### Folders

*This asset field type is not supported in web builds. See [Files](#list-of-paths) for a web compatible way of loading a collection of files.*
*This asset field type is not supported in web builds. File paths need to be known on the web. See [the next section](#lists-of-assets) for a web compatible way of loading a collection of files.*

You can load all files in a folder as a vector of untyped handles. This field requires the additional derive macro attribute `collection`:
```rust
Expand Down Expand Up @@ -203,9 +203,7 @@ struct MyAssets {
})
```

Loading folders is not supported for web builds. If you want to be compatible with Wasm, load you handles from a list of paths instead (see next section).

#### List of paths
#### Lists of assets

If you want to load a list of asset files with the same type into a vector of `Handle<T>`, you can list their paths in an attribute:
```rust
Expand Down Expand Up @@ -238,22 +236,20 @@ use bevy_asset_loader::asset_collection::AssetCollection;

#[derive(AssetCollection, Resource)]
struct MyAssets {
#[asset(key = "files_untyped", collection)]
#[asset(key = "files", collection)]
files_untyped: Vec<HandleUntyped>,
#[asset(key = "files_typed", collection(typed))]
#[asset(key = "files", collection(typed))]
files_typed: Vec<Handle<Image>>,
}
```

The corresponding assets file differs from the folder example:
```ron
({
"files_untyped": Files (
paths: ["images/tree.png", "images/player.png"],
),
"files_typed": Files (
paths: ["images/tree.png", "images/player.png"],
),
"files": [
File(path: "images/tree.png"),
File(path: "images/player.png"),
],
})
```

Expand All @@ -272,9 +268,9 @@ struct MyAssets {
folder: HashMap<String, HandleUntyped>,
#[asset(paths("images/player.png", "images/tree.png"), collection(typed, mapped))]
files_typed: HashMap<String, Handle<Image>>,
#[asset(key = "files_untyped", collection(mapped))]
#[asset(key = "files", collection(mapped))]
dynamic_files_untyped: HashMap<String, HandleUntyped>,
#[asset(key = "files_typed", collection(typed, mapped))]
#[asset(key = "files", collection(typed, mapped))]
dynamic_files_typed: HashMap<String, Handle<Image>>,
}
```
Expand Down
9 changes: 5 additions & 4 deletions bevy_asset_loader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ readme = "README.md"
2d = ["bevy/bevy_sprite", "bevy_asset_loader_derive/2d"]
# This feature adds support for bevy's StandardMaterial assets
3d = ["bevy/bevy_pbr", "bevy/bevy_render", "bevy_asset_loader_derive/3d"]
standard_dynamic_assets = ["dep:bevy_common_assets", "dep:serde"]
standard_dynamic_assets = ["dep:bevy_common_assets"]
progress_tracking = ["dep:iyes_progress"]

[dependencies]
Expand All @@ -25,15 +25,15 @@ bevy_asset_loader_derive = { version = "=0.17.0", path = "../bevy_asset_loader_d
anyhow = "1"
path-slash = "0.2"

bevy_common_assets = { version = "0.7.0", features = ["ron"], optional = true }
serde = { version = "1", optional = true }
bevy_common_assets = { git = "https://github.com/NiklasEi/bevy_common_assets", branch = "ron_0_9", features = ["ron"], optional = true }
serde = { version = "1" }
iyes_progress = { version = "0.9.0", optional = true }

[dev-dependencies]
bevy = { version = "0.11", features = ["vorbis"] }
anyhow = "1"
iyes_progress = { version = "0.9.0" }
bevy_common_assets = { version = "0.7.0", features = ["ron"] }
bevy_common_assets = { git = "https://github.com/NiklasEi/bevy_common_assets", branch = "ron_0_9", features = ["ron"] }
serde = { version = "1" }
trybuild = { version = "1.0" }

Expand Down Expand Up @@ -95,3 +95,4 @@ required-features = ["2d", "3d", "standard_dynamic_assets"]
[[example]]
name = "custom_dynamic_assets"
path = "examples/custom_dynamic_assets.rs"
required-features = ["2d", "standard_dynamic_assets"]
8 changes: 8 additions & 0 deletions bevy_asset_loader/assets/custom.my-assets.ron
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
bottom_layer: "images/tree.png",
top_layer: "images/player.png",
),
"tree": File(path: "images/tree.png"),
"images": [
CombinedImage (
bottom_layer: "images/tree.png",
top_layer: "images/player.png",
),
File(path: "images/player.png")
],
"cube": Cube (
size: 1.3,
),
Expand Down
4 changes: 4 additions & 0 deletions bevy_asset_loader/assets/dynamic_asset.assets.ron
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@
"sounds.background": File (
path: "audio/background.ogg",
),
"images": [
File(path: "images/tree.png"),
File(path: "images/player.png")
],
})
14 changes: 8 additions & 6 deletions bevy_asset_loader/assets/full_dynamic_collection.assets.ron
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
"folder_typed": Folder (
path: "images",
),
"files_untyped": Files (
paths: ["images/tree.png", "images/player.png"],
),
"files_typed": Files (
paths: ["images/tree.png", "images/player.png"],
),
"files_untyped": [
File(path: "images/tree.png"),
File(path: "images/player.png")
],
"files_typed": [
File(path: "images/tree.png"),
File(path: "images/player.png")
],
})
53 changes: 33 additions & 20 deletions bevy_asset_loader/examples/custom_dynamic_assets.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy::core_pipeline::clear_color::ClearColorConfig;
use bevy::prelude::*;
use bevy::reflect::{TypePath, TypeUuid};
use bevy::utils::HashMap;
use bevy_asset_loader::dynamic_asset::{DynamicAssetMap, OneOrManyDynamicAssets};
use bevy_asset_loader::prelude::*;
use bevy_common_assets::ron::RonAssetPlugin;

Expand All @@ -10,17 +10,19 @@ fn main() {
.insert_resource(Msaa::Off)
.add_plugins((
DefaultPlugins,
RonAssetPlugin::<CustomDynamicAssetCollection>::new(&["my-assets.ron"]),
// We need to make sure that our dynamic asset collections can be loaded from the asset file
// You could also use other file formats than `ron` here
// Leave away [`OneOrManyDynamicAssets`] if you don't want to support vectors of your dynamic asset definitions
RonAssetPlugin::<DynamicAssetMap<OneOrManyDynamicAssets<CustomDynamicAsset>>>::new(&[
"my-assets.ron",
]),
))
// We need to make sure that our dynamic asset collections can be loaded from the asset file
.add_state::<MyStates>()
.add_loading_state(
LoadingState::new(MyStates::AssetLoading).continue_to_state(MyStates::Next),
)
.register_dynamic_asset_collection::<_, CustomDynamicAssetCollection>(
MyStates::AssetLoading,
)
.add_dynamic_collection_to_loading_state::<_, CustomDynamicAssetCollection>(
.register_dynamic_asset::<_, CustomDynamicAsset>(MyStates::AssetLoading)
.add_dynamic_collection_to_loading_state::<_, CustomDynamicAsset>(
MyStates::AssetLoading,
"custom.my-assets.ron",
)
Expand Down Expand Up @@ -72,12 +74,26 @@ fn render_stuff(mut commands: Commands, assets: Res<MyAssets>) {
transform: Transform::from_xyz(0.0, 200.0, 0.0),
..default()
});
// The two images that are part of the collection in `custom.my-assets.ron`
// The first is the combined image, the second is the player sprite
commands.spawn(SpriteBundle {
texture: assets.images[0].clone(),
transform: Transform::from_xyz(-200.0, 200.0, 0.0),
..default()
});
commands.spawn(SpriteBundle {
texture: assets.images[1].clone(),
transform: Transform::from_xyz(200.0, 200.0, 0.0),
..default()
});
}

#[derive(AssetCollection, Resource)]
struct MyAssets {
#[asset(key = "combined_image")]
combined_image: Handle<Image>,
#[asset(key = "images", collection(typed))]
images: Vec<Handle<Image>>,
#[asset(key = "tree_standard_material")]
tree_standard_material: Handle<StandardMaterial>,
#[asset(key = "player_standard_material")]
Expand All @@ -86,7 +102,8 @@ struct MyAssets {
cube: Handle<Mesh>,
}

#[derive(serde::Deserialize, Debug, Clone)]
#[derive(serde::Deserialize, Debug, Clone, TypeUuid, TypePath)]
#[uuid = "28dc82ab-d5f5-4d72-b0c4-e2b231367c35"]
enum CustomDynamicAsset {
CombinedImage {
bottom_layer: String,
Expand All @@ -99,6 +116,9 @@ enum CustomDynamicAsset {
Cube {
size: f32,
},
// This allows us to use all the standard dynamic assets in the same files as our custom ones
#[serde(untagged)]
Standard(StandardDynamicAsset),
}

impl DynamicAsset for CustomDynamicAsset {
Expand All @@ -118,12 +138,16 @@ impl DynamicAsset for CustomDynamicAsset {
base_color_texture, ..
} => vec![asset_server.load_untyped(base_color_texture)],
CustomDynamicAsset::Cube { .. } => vec![],
CustomDynamicAsset::Standard(standard) => standard.load(asset_server),
}
}

// This method is called when all asset handles returned from `load` are done loading.
// The handles that you return, should also be loaded.
fn build(&self, world: &mut World) -> Result<DynamicAssetType, anyhow::Error> {
if let CustomDynamicAsset::Standard(standard) = self {
return standard.build(world);
}
let cell = world.cell();
let asset_server = cell
.get_resource::<AssetServer>()
Expand Down Expand Up @@ -192,18 +216,7 @@ impl DynamicAsset for CustomDynamicAsset {

Ok(DynamicAssetType::Single(handle))
}
}
}
}

#[derive(serde::Deserialize, TypeUuid, TypePath)]
#[uuid = "18dc82eb-d5f5-4d72-b0c4-e2b234367c35"]
pub struct CustomDynamicAssetCollection(HashMap<String, CustomDynamicAsset>);

impl DynamicAssetCollection for CustomDynamicAssetCollection {
fn register(&self, dynamic_assets: &mut DynamicAssets) {
for (key, asset) in self.0.iter() {
dynamic_assets.register_asset(key, Box::new(asset.clone()));
CustomDynamicAsset::Standard(_) => unreachable!("standard assets are already handled"),
}
}
}
Expand Down
20 changes: 16 additions & 4 deletions bevy_asset_loader/examples/dynamic_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn main() {
.add_loading_state(
LoadingState::new(MyStates::AssetLoading).continue_to_state(MyStates::Next),
)
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAssetCollection>(
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAsset>(
MyStates::AssetLoading,
"dynamic_asset.assets.ron",
)
Expand All @@ -36,6 +36,8 @@ struct ImageAssets {
player: Handle<TextureAtlas>,
#[asset(key = "image.tree")]
tree: Handle<Image>,
#[asset(key = "images", collection(typed))]
images: Vec<Handle<Image>>,
}

#[derive(AssetCollection, Resource)]
Expand All @@ -46,8 +48,6 @@ struct AudioAssets {

fn spawn_player_and_tree(mut commands: Commands, image_assets: Res<ImageAssets>) {
commands.spawn(Camera2dBundle::default());
let mut transform = Transform::from_translation(Vec3::new(0., 0., 1.));
transform.scale = Vec3::splat(0.5);
commands
.spawn(SpriteSheetBundle {
transform: Transform {
Expand All @@ -65,9 +65,21 @@ fn spawn_player_and_tree(mut commands: Commands, image_assets: Res<ImageAssets>)
.insert(Player);
commands.spawn(SpriteBundle {
texture: image_assets.tree.clone(),
transform: Transform::from_translation(Vec3::new(50., 30., 1.)),
transform: Transform::from_translation(Vec3::new(0., 30., 1.)),
..Default::default()
});

for (index, image) in image_assets.images.iter().enumerate() {
commands.spawn(SpriteBundle {
texture: image.clone(),
transform: Transform::from_translation(Vec3::new(
-50. + 100. * index as f32,
-100.,
1.,
)),
..Default::default()
});
}
}

fn play_background_audio(mut commands: Commands, audio_assets: Res<AudioAssets>) {
Expand Down
2 changes: 1 addition & 1 deletion bevy_asset_loader/examples/full_dynamic_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn main() {
.add_loading_state(
LoadingState::new(MyStates::AssetLoading).continue_to_state(MyStates::Next),
)
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAssetCollection>(
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAsset>(
MyStates::AssetLoading,
"full_dynamic_collection.assets.ron",
)
Expand Down
Loading
Loading