use std::sync::mpsc::Receiver;
use std::sync::Mutex;
use bevy::prelude::*;
use crate::{PhysicsSchedule, PhysicsSet};
#[derive(Resource, Deref, DerefMut)]
struct ChannelReceiver<T>(Mutex<Receiver<T>>);
pub trait AppExtensions {
fn add_physics_event<T: Message>(&mut self) -> &mut Self;
fn add_event_channel<T: Message>(&mut self, receiver: Receiver<T>) -> &mut Self;
fn add_physics_event_channel<T: Message>(&mut self, receiver: Receiver<T>) -> &mut Self;
}
impl AppExtensions for App {
fn add_physics_event<T: Message>(&mut self) -> &mut Self {
if !self.world().contains_resource::<Messages<T>>() {
self.init_resource::<Messages<T>>();
}
self
}
fn add_event_channel<T: Message>(&mut self, receiver: Receiver<T>) -> &mut Self {
assert!(
!self.world().contains_resource::<ChannelReceiver<T>>(),
"this event channel is already initialized",
);
self.add_message::<T>();
self.add_systems(PhysicsSchedule, (
channel_to_event::<T>,
).before(PhysicsSet::Create));
self.insert_resource(ChannelReceiver(Mutex::new(receiver)));
self
}
fn add_physics_event_channel<T: Message>(&mut self, receiver: Receiver<T>) -> &mut Self {
assert!(
!self.world().contains_resource::<ChannelReceiver<T>>(),
"this event channel is already initialized",
);
self.add_physics_event::<T>();
self.add_systems(PhysicsSchedule, (
channel_to_event::<T>,
).before(PhysicsSet::Create));
self.insert_resource(ChannelReceiver(Mutex::new(receiver)));
self
}
}
fn channel_to_event<T: Message>(
receiver: Res<ChannelReceiver<T>>,
mut writer: MessageWriter<T>,
) {
let events = receiver.lock().expect("unable to acquire mutex lock");
writer.write_batch(events.try_iter());
}