codecraft 0.1.1

A minimalist 3D game engine built on parts of Bevy (ECS, color) with wgpu and winit: OpenPBR materials, clustered lighting, an immediate-mode UI, audio and gamepad haptics
Documentation
//! Minimal `App`/`Plugin` scaffolding on top of `bevy_ecs`.
//!
//! This crate only needs systems, components and a way to group them into
//! reusable plugins (like [`crate::ui::UiPlugin`]) — not a full engine, so we
//! skip pulling in `bevy_app` and its own windowing/rendering integration,
//! which would fight with our own `winit`/`wgpu` setup in [`crate::gpu`].
use bevy_ecs::system::ScheduleSystem;

pub use bevy_ecs::prelude::*;

/// A reusable bundle of components, resources and systems.
pub trait Plugin {
    fn build(&self, app: &mut Application);
}

/// Owns the ECS `World` plus a startup schedule (run once) and an update
/// schedule (run every [`App::update`] call).
pub struct Application {
    pub world: World,
    startup: Schedule,
    update: Schedule,
    startup_done: bool,
}

impl Application {
    pub fn new() -> Self {
        Self {
            world: World::new(),
            startup: Schedule::default(),
            update: Schedule::default(),
            startup_done: false,
        }
    }

    pub fn add_plugin(&mut self, plugin: impl Plugin) -> &mut Self {
        plugin.build(self);
        self
    }

    pub fn add_startup_systems<M>(
        &mut self,
        systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
    ) -> &mut Self {
        self.startup.add_systems(systems);
        self
    }

    pub fn add_update_systems<M>(
        &mut self,
        systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
    ) -> &mut Self {
        self.update.add_systems(systems);
        self
    }

    pub fn insert_resource<R: Resource>(&mut self, resource: R) -> &mut Self {
        self.world.insert_resource(resource);
        self
    }

    /// Adds a resource's default, leaving any already there alone.
    ///
    /// For a plugin that reads something another plugin owns: it can stand on
    /// its own without clobbering the other's state when both are installed.
    pub fn init_resource<R: Resource + FromWorld>(&mut self) -> &mut Self {
        self.world.init_resource::<R>();
        self
    }

    /// Runs the startup schedule once (on the first call), then the update schedule.
    pub fn update(&mut self) {
        if !self.startup_done {
            self.startup.run(&mut self.world);
            self.startup_done = true;
        }
        self.update.run(&mut self.world);
    }
}

impl Default for Application {
    fn default() -> Self {
        Self::new()
    }
}