feat: add entity handles and a bevy channel abstraction

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2025-06-28 12:56:40 +02:00
committed by Nova King
parent 85bb21414d
commit 600eab9d2a
9 changed files with 163 additions and 98 deletions

32
src/core/bevy_channel.rs Normal file
View File

@@ -0,0 +1,32 @@
use std::sync::OnceLock;
use bevy::prelude::*;
use tokio::sync::mpsc::{self, error::TryRecvError};
#[derive(Resource)]
pub struct BevyChannelReader<T: Send + Sync + 'static>(mpsc::UnboundedReceiver<T>);
pub struct BevyChannel<T: Send + Sync + 'static>(OnceLock<mpsc::UnboundedSender<T>>);
impl<T: Send + Sync + 'static> BevyChannel<T> {
pub const fn new() -> Self {
Self(OnceLock::new())
}
pub fn init(&self, app: &mut App) {
let (tx, rx) = mpsc::unbounded_channel();
self.0.set(tx).unwrap();
app.insert_resource(BevyChannelReader(rx));
}
pub fn send(&self, msg: T) -> Option<()> {
self.0.get()?.send(msg).ok()
}
}
impl<T: Send + Sync + 'static> BevyChannelReader<T> {
pub fn read(&mut self) -> Option<T> {
match self.0.try_recv() {
Ok(v) => Some(v),
Err(TryRecvError::Disconnected) => panic!("bevy channel should never disconnect"),
Err(TryRecvError::Empty) => None,
}
}
}

12
src/core/color.rs Normal file
View File

@@ -0,0 +1,12 @@
use stardust_xr::values::color::{AlphaColor, Rgb, color_space::LinearRgb};
pub trait ColorConvert {
fn to_bevy(&self) -> bevy::color::Color;
}
// even tho its supposed to be linear the values have to be interpreted as Srgba to produce the
// correct result because StereoKit used Srgba while it was assumed that is uses linear rgba
impl ColorConvert for AlphaColor<f32, Rgb<f32, LinearRgb>> {
fn to_bevy(&self) -> bevy::color::Color {
bevy::color::Color::srgba(self.c.r, self.c.g, self.c.b, self.a)
}
}

33
src/core/entity_handle.rs Normal file
View File

@@ -0,0 +1,33 @@
use bevy::prelude::*;
use super::bevy_channel::{BevyChannel, BevyChannelReader};
pub struct EntityHandlePlugin;
impl Plugin for EntityHandlePlugin {
fn build(&self, app: &mut App) {
DESTROY.init(app);
app.add_systems(PreUpdate, despawn);
}
}
fn despawn(mut cmds: Commands, mut reader: ResMut<BevyChannelReader<Entity>>) {
while let Some(e) = reader.read() {
cmds.entity(e).despawn();
}
}
static DESTROY: BevyChannel<Entity> = BevyChannel::new();
#[derive(Deref, DerefMut, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct EntityHandle(pub Entity);
impl Drop for EntityHandle {
fn drop(&mut self) {
if DESTROY.send(self.0).is_none() {
error!("Entity Destroy channel not open");
}
}
}
impl From<Entity> for EntityHandle {
fn from(value: Entity) -> Self {
Self(value)
}
}

View File

@@ -8,3 +8,5 @@ pub mod resource;
pub mod scenegraph;
pub mod task;
pub mod color;
pub mod entity_handle;
pub mod bevy_channel;