mirror of
https://github.com/Xevion/smart-rgb.git
synced 2025-12-05 23:16:23 -06:00
147 lines
4.2 KiB
Rust
147 lines
4.2 KiB
Rust
//! Minimal ECS app wrapper to replace Bevy's App
|
|
|
|
use bevy_ecs::message::{Message, Messages};
|
|
use bevy_ecs::prelude::*;
|
|
use bevy_ecs::schedule::{IntoScheduleConfigs, ScheduleLabel, Schedules};
|
|
use bevy_ecs::system::ScheduleSystem;
|
|
use std::fmt::Debug;
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
|
|
pub struct Startup;
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
|
|
pub struct Update;
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
|
|
pub struct Last;
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
|
|
pub struct Fixed;
|
|
|
|
pub struct App {
|
|
world: World,
|
|
}
|
|
|
|
impl App {
|
|
pub fn new() -> Self {
|
|
let mut world = World::new();
|
|
|
|
// Initialize schedules
|
|
let mut schedules = Schedules::new();
|
|
schedules.insert(Schedule::new(Startup));
|
|
schedules.insert(Schedule::new(Update));
|
|
schedules.insert(Schedule::new(Last));
|
|
schedules.insert(Schedule::new(Fixed));
|
|
|
|
world.insert_resource(schedules);
|
|
|
|
Self { world }
|
|
}
|
|
|
|
pub fn world(&self) -> &World {
|
|
&self.world
|
|
}
|
|
|
|
pub fn world_mut(&mut self) -> &mut World {
|
|
&mut self.world
|
|
}
|
|
|
|
pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
|
|
self.world.insert_resource(resource);
|
|
self
|
|
}
|
|
|
|
pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {
|
|
self.world.init_resource::<R>();
|
|
self
|
|
}
|
|
|
|
pub fn insert_non_send_resource<R: 'static>(&mut self, resource: R) -> &mut Self {
|
|
self.world.insert_non_send_resource(resource);
|
|
self
|
|
}
|
|
|
|
pub fn add_message<M: Message>(&mut self) -> &mut Self {
|
|
if !self.world.contains_resource::<Messages<M>>() {
|
|
self.world.init_resource::<Messages<M>>();
|
|
|
|
// Add system to update this message type each frame
|
|
self.add_systems(Last, |mut messages: ResMut<Messages<M>>| {
|
|
messages.update();
|
|
});
|
|
}
|
|
self
|
|
}
|
|
|
|
pub fn add_systems<M>(&mut self, schedule: impl ScheduleLabel, systems: impl IntoScheduleConfigs<ScheduleSystem, M>) -> &mut Self {
|
|
let mut schedules = self.world.resource_mut::<Schedules>();
|
|
if let Some(schedule_inst) = schedules.get_mut(schedule) {
|
|
schedule_inst.add_systems(systems);
|
|
}
|
|
self
|
|
}
|
|
|
|
pub fn update(&mut self) {
|
|
// Remove schedules temporarily to avoid resource_scope conflicts
|
|
let mut schedules = self.world.remove_resource::<Schedules>().unwrap();
|
|
|
|
// Run Update schedule
|
|
if let Some(schedule) = schedules.get_mut(Update) {
|
|
schedule.run(&mut self.world);
|
|
}
|
|
|
|
// Run Last schedule (includes event updates)
|
|
if let Some(schedule) = schedules.get_mut(Last) {
|
|
schedule.run(&mut self.world);
|
|
}
|
|
|
|
// Re-insert schedules
|
|
self.world.insert_resource(schedules);
|
|
}
|
|
|
|
pub fn run_startup(&mut self) {
|
|
let _span = tracing::trace_span!("run_startup_schedule").entered();
|
|
|
|
// Remove schedules temporarily to avoid resource_scope conflicts
|
|
let mut schedules = self.world.remove_resource::<Schedules>().unwrap();
|
|
|
|
// Run Startup schedule
|
|
if let Some(schedule) = schedules.get_mut(Startup) {
|
|
schedule.run(&mut self.world);
|
|
}
|
|
|
|
// Re-insert schedules
|
|
self.world.insert_resource(schedules);
|
|
}
|
|
|
|
pub fn finish(&mut self) {
|
|
// Finalize schedules
|
|
let mut schedules = self.world.remove_resource::<Schedules>().unwrap();
|
|
|
|
let system_count: usize = schedules.iter().map(|(_, schedule)| schedule.systems().map(|iter| iter.count()).unwrap_or(0)).sum();
|
|
|
|
let _span = tracing::trace_span!("finish_schedules", system_count = system_count).entered();
|
|
|
|
for (_, schedule) in schedules.iter_mut() {
|
|
schedule.graph_mut().initialize(&mut self.world);
|
|
}
|
|
|
|
self.world.insert_resource(schedules);
|
|
}
|
|
|
|
pub fn cleanup(&mut self) {
|
|
// Any cleanup needed before running
|
|
}
|
|
}
|
|
|
|
impl Default for App {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
/// Plugin trait for modular setup
|
|
pub trait Plugin {
|
|
fn build(&self, app: &mut App);
|
|
}
|