# App, Modules & Scheduling

`oxide_engine::app` is where the Stage-5 core framework comes together. An
[`App`] owns the shared engine state and a [`Schedule`] of systems; functionality
is added by **modules**. This is the spine the rest of the engine plugs into: the
engine is *composed* rather than hard-wired, and an exported game compiles in
only the modules it registers.

## The App

An `App` owns:

- the active [`Scene`](scene.md),
- the shared [`AssetServer`](assets.md),
- the [`TypeRegistry`](reflection.md) (dual-editable components),
- the project's [`LayerRegistry`](layers.md),
- frame [`Time`], and
- arbitrary user **resources** (a type-keyed store).

```rust
use oxide_engine::app::{App, DefaultModules};

let mut app = App::new();
app.add_modules(DefaultModules);
app.update(1.0 / 60.0); // advance one frame
```

> Note: the application core is `oxide_engine::app::App`. It is intentionally
> *not* in the prelude, to avoid clashing with the windowing
> [`App`](windowing.md) trait (the per-window event handler). Import it directly.

### Resources

Resources are shared singletons addressed by type — the home for state that
isn't per-entity (an input map, a physics world, game settings):

```rust
# use oxide_engine::app::App;
# let mut app = App::new();
app.insert_resource(0u32);
*app.get_resource_mut::<u32>().unwrap() += 1;
assert_eq!(app.get_resource::<u32>(), Some(&1));
```

## Systems and the schedule

A **system** is any `FnMut(&mut App)` attached to a [`Schedule`] phase. Phases run
in a fixed order each frame; within a phase, systems run in registration order,
so behavior is fully deterministic.

| Phase | Purpose |
|-------|---------|
| `First` | start-of-frame bookkeeping |
| `Input` | gather input (Stage 7) |
| `PreUpdate` | engine work before game logic |
| `FixedUpdate` | fixed-timestep work; runs **0..n** times per frame (physics, Stage 9) |
| `Update` | per-frame game logic |
| `PostUpdate` | engine work after game logic |
| `Render` | drawing (Stage 5 pipeline onward) |
| `Last` | end-of-frame cleanup |

```rust
use oxide_engine::app::{App, Schedule};
use oxide_engine::prelude::*;

let mut app = App::new();
app.scene.spawn("spinner", Transform::IDENTITY);
app.add_system(Schedule::Update, |app| {
    let dt = app.time.delta;
    for e in app.scene.entities().collect::<Vec<_>>() {
        if let Some(mut t) = app.scene.get_mut::<Transform>(e) {
            t.translation.x += dt;
        }
    }
});
```

Systems get exclusive `&mut App` while running (the schedule is moved out of the
app for the duration), so a system can freely read and mutate the scene,
resources, and assets.

### Fixed timestep

`FixedUpdate` is driven by an accumulator so simulation is frame-rate
independent: each `update(dt)` runs as many whole `fixed_delta` steps as the
accumulated time allows. The number of steps per frame is **capped** so a long
stall (a breakpoint, a hitch) cannot trigger an unbounded catch-up "spiral of
death". Set the rate with `app.set_fixed_timestep(seconds)` (default 1/60).

The whole frame's scheduling overhead is a few dozen nanoseconds even with
several systems registered (see `cargo bench -p oxide-engine --bench app`), so it
is lost in the noise next to any real per-frame work.

## Modules

A [`Module`] is the unit of engine extension. Its [`build`](Module::build) method
registers systems, component types, asset loaders, and resources through the
`App` facade. Everything registered during `build` is **attributed to the
module**, so it can be enabled, disabled, or removed as one unit.

```rust
use oxide_engine::app::{App, Module, Schedule};

struct HeartbeatModule;
impl Module for HeartbeatModule {
    fn name(&self) -> &'static str { "heartbeat" }
    fn build(&self, app: &mut App) {
        app.insert_resource(0u64);
        app.add_system(Schedule::Update, |app| {
            *app.get_resource_mut::<u64>().unwrap() += 1;
        });
    }
}

let mut app = App::new();
app.add_module(HeartbeatModule);
```

### Enable / disable / remove

These power the editor's module management (Stage 6) and the "ship only what you
use" principle:

```rust
# use oxide_engine::app::{App, Module, Schedule};
# struct HeartbeatModule;
# impl Module for HeartbeatModule {
#     fn name(&self) -> &'static str { "heartbeat" }
#     fn build(&self, app: &mut App) {}
# }
# let mut app = App::new();
# app.add_module(HeartbeatModule);
app.set_module_enabled("heartbeat", false); // systems skipped, nothing removed
app.set_module_enabled("heartbeat", true);  // resumes
app.remove_module("heartbeat");             // systems, types, loaders, resources gone
```

`remove_module` undoes every registration the module made — its systems,
reflected types, asset loaders, and resources — leaving no dangling references.
Disabling is the cheap, reversible version (systems are skipped but kept).

### Built-in modules

`DefaultModules` bundles the engine's standard set:

- **`core`** — registers the always-present scene component types (`Transform`,
  `Node`, `Layer`, `Tags`) for reflection, exposing them to the editor and
  scripts.
- **`render`** — registers the renderable `MeshRenderer` component and (as the
  data-driven render pipeline grows) the render-phase systems.

Subsystems from Stage 9 on (physics, audio, …) are built as their own
feature-gated crates, each exposing a `Module`, so a project pays for them only
by registering them.

[`App`]: ../engine/src/app/mod.rs
[`Time`]: ../engine/src/app/mod.rs
[`Schedule`]: ../engine/src/app/schedule.rs
[`Module`]: ../engine/src/app/module.rs
[`Scene`]: ../engine/src/scene/graph.rs
