use core::ops::{Deref, DerefMut};
use bevy::prelude::*;
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
pub struct AgbSoundPlugin {
pub enable_dmg: bool,
pub mixer_frequency: Option<agb::sound::mixer::Frequency>,
}
impl Plugin for AgbSoundPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
PostUpdate,
|mixer: Option<NonSendMut<agb::sound::mixer::Mixer>>| {
if let Some(mut mixer) = mixer {
mixer.frame();
}
},
);
}
fn finish(&self, app: &mut App) {
if self.enable_dmg {
if let Some(sound) = app
.world_mut()
.remove_non_send_resource::<agb::sound::dmg::Sound>()
{
sound.enable();
let channel1 = Channel::<1>::from_sound(&sound);
let channel2 = Channel::<2>::from_sound(&sound);
let noise = Noise(sound.noise());
app.insert_resource(channel1)
.insert_resource(channel2)
.insert_resource(noise);
}
}
if let Some(frequency) = self.mixer_frequency {
if let Some(mixer_controller) = app
.world_mut()
.remove_non_send_resource::<agb::sound::mixer::MixerController>()
{
let mixer_controller = Box::leak(Box::new(mixer_controller));
let mut mixer = mixer_controller.mixer(frequency);
mixer.enable();
app.insert_non_send_resource(mixer);
}
}
}
}
#[derive(Resource, Deref, DerefMut)]
pub struct Sound(agb::sound::dmg::Sound);
#[derive(Resource, Deref, DerefMut)]
pub struct Noise(agb::sound::dmg::Noise);
#[derive(Resource)]
pub struct Channel<const N: usize> {
c1: agb::sound::dmg::Channel1,
c2: agb::sound::dmg::Channel2,
}
impl Deref for Channel<1> {
type Target = agb::sound::dmg::Channel1;
fn deref(&self) -> &Self::Target {
&self.c1
}
}
impl DerefMut for Channel<1> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.c1
}
}
impl Deref for Channel<2> {
type Target = agb::sound::dmg::Channel2;
fn deref(&self) -> &Self::Target {
&self.c2
}
}
impl DerefMut for Channel<2> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.c2
}
}
impl Channel<1> {
fn from_sound(sound: &agb::sound::dmg::Sound) -> Self {
Self {
c1: sound.channel1(),
c2: sound.channel2(),
}
}
}
impl Channel<2> {
fn from_sound(sound: &agb::sound::dmg::Sound) -> Self {
Self {
c1: sound.channel1(),
c2: sound.channel2(),
}
}
}