Compare commits

..

3 Commits

Author SHA1 Message Date
d34c3d6e96 Release 2024-02-09 13:43:14 -06:00
d7e9b1b70c Update changelog. 2024-02-09 13:41:51 -06:00
2080019421 chore: Bump dependencies. 2024-02-09 13:41:01 -06:00
4 changed files with 79 additions and 59 deletions

View File

@ -2,6 +2,22 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## Version 0.5.0 - 2024-02-09
### Bug Fixes
- Clean up `LastAudio` when `Sound` is removed, not `Source`.
### Features
- [**breaking**] Renamed `SynthizerSets::First` to `SynthizerSets::PreUpdate` and moved remaining systems into `PostUpdate`.
- [**breaking**] Removed `Sound.restart`. Clear `Sound.generator` for equivalent functionality.
### Miscellaneous Tasks
- Clean up code.
- Bump dependencies.
## Version 0.4.0 - 2023-07-16 ## Version 0.4.0 - 2023-07-16
### Miscellaneous Tasks ### Miscellaneous Tasks

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bevy_synthizer" name = "bevy_synthizer"
version = "0.4.0" version = "0.5.0"
authors = ["Nolan Darilek <nolan@thewordnerd.info>"] authors = ["Nolan Darilek <nolan@thewordnerd.info>"]
description = "A Bevy plugin for Synthizer, a library for 3D audio and synthesis with a focus on games and VR applications" description = "A Bevy plugin for Synthizer, a library for 3D audio and synthesis with a focus on games and VR applications"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
@ -10,12 +10,11 @@ repository = "https://labs.lightsout.games/projects/bevy_synthizer"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anyhow = "1" bevy = { version = "0.12", default-features = false, features = ["bevy_asset"] }
bevy = { version = "0.11", default-features = false, features = ["bevy_asset"] }
synthizer = "0.5.6" synthizer = "0.5.6"
[dev-dependencies] [dev-dependencies]
bevy = { version = "0.11", default-features = true } bevy = { version = "0.12", default-features = true }
[package.metadata.release] [package.metadata.release]
publish = false publish = false

View File

@ -1,6 +1,6 @@
use std::f32; use std::f32;
use bevy::{asset::LoadState, prelude::*}; use bevy::{asset::LoadedFolder, prelude::*};
use bevy_synthizer::*; use bevy_synthizer::*;
#[derive(Component, Deref, DerefMut)] #[derive(Component, Deref, DerefMut)]
@ -12,46 +12,41 @@ impl Default for RotationTimer {
} }
} }
#[derive(Resource, Default)] #[derive(Resource, Default, Deref, DerefMut)]
struct AssetHandles { struct AssetHandles(Handle<LoadedFolder>);
sounds: Vec<HandleUntyped>,
loaded: bool,
}
fn setup(asset_server: Res<AssetServer>, mut handles: ResMut<AssetHandles>) { fn setup(asset_server: Res<AssetServer>, mut handles: ResMut<AssetHandles>) {
handles.sounds = asset_server.load_folder(".").expect("Failed to load sfx"); **handles = asset_server.load_folder(".");
} }
fn load_and_create( fn load_and_create(
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut handles: ResMut<AssetHandles>, handles: Res<AssetHandles>,
listeners: Query<&Listener>,
) { ) {
if handles.loaded { if !asset_server.is_loaded_with_dependencies(&**handles) {
return;
}
if !listeners.is_empty() {
return; return;
} }
handles.loaded = asset_server
.get_group_load_state(handles.sounds.iter().map(|handle| handle.id()))
== LoadState::Loaded;
if handles.loaded {
commands.spawn(( commands.spawn((
TransformBundle::default(), TransformBundle::default(),
Listener, Listener,
RotationTimer::default(), RotationTimer::default(),
)); ));
let handle = handles.sounds[0].clone(); let handle = asset_server.load("footstep.wav");
let buffer = asset_server.get_handle(handle);
commands.spawn(( commands.spawn((
TransformBundle::from(Transform::from_translation(Vec3::new(10., 0., 0.))), TransformBundle::from(Transform::from_translation(Vec3::new(10., 0., 0.))),
Source::default(), Source::default(),
Sound { Sound {
audio: buffer.into(), audio: handle.into(),
looping: true, looping: true,
..default() ..default()
}, },
)); ));
} }
}
fn rotate_listener(time: Res<Time>, mut query: Query<(&mut RotationTimer, &mut Transform)>) { fn rotate_listener(time: Res<Time>, mut query: Query<(&mut RotationTimer, &mut Transform)>) {
for (mut timer, mut transform) in query.iter_mut() { for (mut timer, mut transform) in query.iter_mut() {

View File

@ -2,39 +2,48 @@
use std::collections::HashMap; use std::collections::HashMap;
use bevy::{ use bevy::{
asset::{AssetLoader, LoadContext, LoadedAsset}, asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext},
prelude::*, prelude::*,
reflect::{TypePath, TypeUuid}, reflect::TypePath,
transform::TransformSystem, transform::TransformSystem,
utils::BoxedFuture, utils::{
thiserror::{self, Error},
BoxedFuture,
},
}; };
pub use synthizer as syz; pub use synthizer as syz;
#[derive(Clone, Debug, Deref, DerefMut, PartialEq, Eq, TypePath, TypeUuid)] #[derive(Asset, Clone, Debug, Deref, DerefMut, PartialEq, Eq, TypePath)]
#[uuid = "6b6b533a-bb1f-11ec-bda2-00155d8fdde9"]
pub struct Buffer(syz::Buffer); pub struct Buffer(syz::Buffer);
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
struct BufferAssetLoader; struct BufferAssetLoader;
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum BufferAssetLoaderError {
#[error("Could not load asset: {0}")]
Io(#[from] std::io::Error),
#[error("Synthizer error: {0}")]
SynthizerError(#[from] synthizer::Error),
}
impl AssetLoader for BufferAssetLoader { impl AssetLoader for BufferAssetLoader {
type Asset = Buffer;
type Settings = ();
type Error = BufferAssetLoaderError;
fn load<'a>( fn load<'a>(
&'a self, &'a self,
bytes: &'a [u8], reader: &'a mut Reader,
load_context: &'a mut LoadContext, _settings: &'a (),
) -> BoxedFuture<'a, Result<(), anyhow::Error>> { _load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Box::pin(async move { Box::pin(async move {
let buffer: Option<Buffer> = let mut bytes = Vec::new();
match load_context.path().extension().unwrap().to_str().unwrap() { reader.read_to_end(&mut bytes).await?;
"flac" | "mp3" | "wav" => { let buffer = syz::Buffer::from_encoded_data(&bytes).map(Buffer)?;
syz::Buffer::from_encoded_data(bytes).map(Buffer).ok() Ok(buffer)
}
_ => None,
};
if let Some(buffer) = buffer {
load_context.set_default_asset(LoadedAsset::new(buffer));
}
Ok(())
}) })
} }
@ -374,7 +383,7 @@ fn change_panner_strategy(
check.push(entity); check.push(entity);
} }
} }
for entity in removed.iter() { for entity in removed.read() {
check.push(entity); check.push(entity);
} }
for entity in check.iter() { for entity in check.iter() {
@ -575,7 +584,7 @@ fn update_sound_playback_state(query: Query<&Sound>) {
} }
fn remove_sound(mut last_buffer: ResMut<LastAudio>, mut removed: RemovedComponents<Sound>) { fn remove_sound(mut last_buffer: ResMut<LastAudio>, mut removed: RemovedComponents<Sound>) {
for entity in removed.iter() { for entity in removed.read() {
last_buffer.remove(&entity); last_buffer.remove(&entity);
} }
} }
@ -723,7 +732,7 @@ impl Plugin for SynthizerPlugin {
}; };
context.enable_events().expect("Failed to enable events"); context.enable_events().expect("Failed to enable events");
let context = Context(context); let context = Context(context);
app.add_asset::<Buffer>() app.init_asset::<Buffer>()
.init_asset_loader::<BufferAssetLoader>() .init_asset_loader::<BufferAssetLoader>()
.register_type::<DistanceRef>() .register_type::<DistanceRef>()
.register_type::<DistanceMax>() .register_type::<DistanceMax>()
@ -740,14 +749,15 @@ impl Plugin for SynthizerPlugin {
.add_event::<SynthizerEvent>() .add_event::<SynthizerEvent>()
.add_systems( .add_systems(
PreUpdate, PreUpdate,
(sync_config, swap_buffers, change_panner_strategy).in_set(SynthizerSets::PreUpdate), (sync_config, swap_buffers, change_panner_strategy)
.in_set(SynthizerSets::PreUpdate),
) )
.add_systems( .add_systems(
PostUpdate, PostUpdate,
(add_sound_without_source, add_source_handle, add_generator) (add_sound_without_source, add_source_handle, add_generator)
.in_set(SynthizerSets::UpdateHandles), .in_set(SynthizerSets::UpdateHandles),
) )
.configure_set( .configure_sets(
PostUpdate, PostUpdate,
SynthizerSets::UpdateHandles.before(SynthizerSets::UpdateProperties), SynthizerSets::UpdateHandles.before(SynthizerSets::UpdateProperties),
) )
@ -761,7 +771,7 @@ impl Plugin for SynthizerPlugin {
.in_set(SynthizerSets::UpdateProperties) .in_set(SynthizerSets::UpdateProperties)
.after(TransformSystem::TransformPropagate), .after(TransformSystem::TransformPropagate),
) )
.configure_set( .configure_sets(
PostUpdate, PostUpdate,
SynthizerSets::UpdateProperties.before(SynthizerSets::UpdateState), SynthizerSets::UpdateProperties.before(SynthizerSets::UpdateState),
) )
@ -770,7 +780,7 @@ impl Plugin for SynthizerPlugin {
(update_source_playback_state, update_sound_playback_state) (update_source_playback_state, update_sound_playback_state)
.in_set(SynthizerSets::UpdateState), .in_set(SynthizerSets::UpdateState),
) )
.configure_set( .configure_sets(
PostUpdate, PostUpdate,
SynthizerSets::UpdateState.before(SynthizerSets::Last), SynthizerSets::UpdateState.before(SynthizerSets::Last),
) )