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

Remove audio + assets modules in favor of raw Bevy APIs and thin LoadResource API #264

Merged
merged 12 commits into from
Aug 15, 2024
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ The best way to get started is to play around with what you find in [`src/demo/`

This template comes with a basic project structure that you may find useful:

| Path | Description |
|------------------------------------------|--------------------------------------------------------------------------------|
| [`src/lib.rs`](./src/lib.rs) | App setup |
| [`src/assets.rs`](./src/assets.rs) | Definition of assets that will be preloaded before the game starts |
| [`src/audio/`](./src/audio) | Commands for playing SFX and music |
| [`src/demo/`](./src/demo) | Example game mechanics & content (replace with your own code) |
| [`src/dev_tools.rs`](./src/dev_tools.rs) | Dev tools for dev builds (press \` aka backtick to toggle) |
| [`src/screens/`](./src/screens) | Splash screen, title screen, playing screen, etc. |
| [`src/theme/`](./src/theme) | Reusable UI widgets & theming |
| Path | Description |
| -------------------------------------------------- | -------------------------------------------------------------------------- |
| [`src/lib.rs`](./src/lib.rs) | App setup |
| [`src/asset_tracking.rs`](./src/asset_tracking.rs) | A simple, high-level way to load collections of asset handles as resources |
| [`src/audio/`](./src/audio) | Commands for playing SFX and music |
| [`src/demo/`](./src/demo) | Example game mechanics & content (replace with your own code) |
| [`src/dev_tools.rs`](./src/dev_tools.rs) | Dev tools for dev builds (press \` aka backtick to toggle) |
| [`src/screens/`](./src/screens) | Splash screen, title screen, playing screen, etc. |
| [`src/theme/`](./src/theme) | Reusable UI widgets & theming

Feel free to move things around however you want, though.

Expand Down
59 changes: 59 additions & 0 deletions src/asset_tracking.rs
cart marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! A simple, high-level way to load collections of asset handles as resources

use bevy::prelude::*;

pub(super) fn plugin(app: &mut App) {
app.init_resource::<ResourceHandles>()
.add_systems(PreUpdate, load_resource_assets);
}

pub trait LoadResource {
/// This will load the [`Resource`] as an [`Asset`]. When all of its asset dependencies
/// have been loaded, it will be inserted as a resource. This ensures that the resource only
/// exists when the assets are ready.
fn load_resource<T: Resource + Asset + Clone + FromWorld>(&mut self) -> &mut Self;
}

impl LoadResource for App {
fn load_resource<T: Resource + Asset + Clone + FromWorld>(&mut self) -> &mut Self {
self.init_asset::<T>();
let world = self.world_mut();
let value = T::from_world(world);
let assets = world.resource::<AssetServer>();
let handle = assets.add(value);
let mut handles = world.resource_mut::<ResourceHandles>();
handles.waiting.push((handle.untyped(), |world, handle| {
let assets = world.resource::<Assets<T>>();
if let Some(value) = assets.get(handle.id().typed::<T>()) {
world.insert_resource(value.clone());
}
}));
self
}
}

/// A function that inserts a loaded resource.
type InsertLoadedResource = fn(&mut World, &UntypedHandle);

#[derive(Resource, Default)]
struct ResourceHandles {
waiting: Vec<(UntypedHandle, InsertLoadedResource)>,
#[allow(unused)]
finished: Vec<UntypedHandle>,
}

fn load_resource_assets(world: &mut World) {
world.resource_scope(|world, mut resource_handles: Mut<ResourceHandles>| {
world.resource_scope(|world, assets: Mut<AssetServer>| {
for _ in 0..resource_handles.waiting.len() {
cart marked this conversation as resolved.
Show resolved Hide resolved
let (handle, insert_fn) = resource_handles.waiting.pop().unwrap();
if assets.is_loaded_with_dependencies(&handle) {
insert_fn(world, &handle);
resource_handles.finished.push(handle);
} else {
resource_handles.waiting.push((handle, insert_fn));
}
}
});
});
}
114 changes: 0 additions & 114 deletions src/assets.rs

This file was deleted.

37 changes: 37 additions & 0 deletions src/audio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use bevy::prelude::*;

/// An organizational marker component that should be added to a spawned [`AudioBundle`] if it is in the
/// general "music" category (ex: global background music, soundtrack, etc).
///
/// This can then be used to query for and operate on sounds in that category. For example:
///
/// ```
benfrankel marked this conversation as resolved.
Show resolved Hide resolved
/// use bevy::prelude::*;
/// use bevy_quickstart::audio::Music;
///
/// fn set_music_volume(sink_query: Query<&AudioSink, With<Music>>) {
/// for sink in &sink_query {
/// sink.set_volume(0.5);
/// }
/// }
/// ```
#[derive(Component, Default)]
pub struct Music;

/// An organizational marker component that should be added to a spawned [`AudioBundle`] if it is in the
/// general "sound effect" category (ex: footsteps, the sound of a magic spell, a door opening).
///
/// This can then be used to query for and operate on sounds in that category. For example:
///
/// ```
/// use bevy::prelude::*;
/// use bevy_quickstart::audio::SoundEffect;
///
/// fn set_sound_effect_volume(sink_query: Query<&AudioSink, With<SoundEffect>>) {
/// for sink in &sink_query {
/// sink.set_volume(0.5);
/// }
/// }
/// ```
#[derive(Component, Default)]
pub struct SoundEffect;
78 changes: 0 additions & 78 deletions src/audio/bgm.rs

This file was deleted.

10 changes: 0 additions & 10 deletions src/audio/mod.rs

This file was deleted.

Loading