Architecture
note
This page is a living document — fill it in as subsystems stabilise.
Subsystem overview
Initialisation order
- Register
res://andcache://from SDL paths - Load configuration in three layers (
engine_defaults→ workspace root → game overrides) →mConfig - Configure logging — apply
mConfiglog levels tolog_manager - Register renderer factories (
assemblyRegistration()) - Create renderer from config — looked up in
RendererRegistryby name - Load
game.json— register per-game URI scheme roots withengine_defaultsfallbacks - Load keybinds (non-fatal if absent)
- Create SDL window with renderer flags
- Construct
ShaderSystem,Scene,SceneGraph - Load and run the game (scenes, scripts)
Design principles
- Encapsulation — the
Engineclass handles its own complete setup;main.cpponly creates it and optionally overrides specific config values. - Config-driven — renderer type, resource paths, and log levels all come from
engine.config.json. No hardcoded paths or types in C++. - No raw
void*— all APIs use typed C++23 abstractions (std::span,tl::expected, etc.). - Reference-only scenes — scenes hold transforms and pointers; all geometry/material data lives in model descriptors.
tl::expectederror handling — fallible public APIs returntl::expected<T, std::string>instead of throwing exceptions.- URI-based resources — all file access uses scheme-mapped URIs (
scenes://,textures://, etc.) with fallback paths and.glitterpakarchive support.