Skip to content

Project Structure

Xavier Beheydt edited this page Jan 31, 2026 · 2 revisions

AetherEngine - Project Structure & Architecture

Version: 0.1.0 Last Updated: 2026-01-30

Table of Contents

  1. Overview
  2. Technical Stack
  3. Directory Structure
  4. Core Concepts
  5. Python Integration
  6. External Tools Integration
  7. Templates
  8. CMake Configuration
  9. Workflow

Overview

AetherEngine is a modern C++23 game engine designed for both 2D and 3D games, with Vulkan rendering, Python scripting, and a strong focus on AI/ML integration. The project follows a modular architecture where:

  • Engine: The core runtime (always compiled)
  • Plugins: Technical extensions to the engine (physics, audio backends)
  • Modules: Reusable gameplay building blocks (FPS framework, inventory system)
  • Games: Final products, linked as external projects via symlinks
┌─────────────────────────────────────────────────────────────────┐
│                        AetherEngine                             │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                      ENGINE CORE                         │   │
│  │  ┌────────┐ ┌──────────┐ ┌───────┐ ┌───────────┐         │   │
│  │  │  Core  │ │ Graphics │ │ Audio │ │ Scripting │         │   │
│  │  └────────┘ └──────────┘ └───────┘ └───────────┘         │   │
│  │  ┌────────┐ ┌──────────┐ ┌───────┐ ┌───────────┐         │   │
│  │  │   ECS  │ │ Network  │ │  AI   │ │  Physics  │         │   │
│  │  └────────┘ └──────────┘ └───────┘ └───────────┘         │   │
│  └──────────────────────────────────────────────────────────┘   │
│                              │                                  │
│                              ▼                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                       PLUGINS                            │   │
│  │         (Technical engine extensions)                    │   │
│  │  ┌────────────────┐ ┌───────────────┐ ┌──────────────┐   │   │
│  │  │  physics_jolt  │ │ audio_openal  │ │ physics_bullet│  │   │
│  │  └────────────────┘ └───────────────┘ └──────────────┘   │   │
│  └──────────────────────────────────────────────────────────┘   │
│                              │                                  │
│                              ▼                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                       MODULES                            │   │
│  │           (Reusable gameplay building blocks)            │   │
│  │  ┌───────────────┐ ┌──────────────┐ ┌─────────────────┐  │   │
│  │  │ fps_framework │ │ inventory    │ │ dialogue_system │  │   │
│  │  └───────────────┘ └──────────────┘ └─────────────────┘  │   │
│  └──────────────────────────────────────────────────────────┘   │
│                              │                                  │
│                              ▼                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                        GAMES                             │   │
│  │              (Final playable products)                   │   │
│  │  ┌─────────────────┐        ┌─────────────────┐          │   │
│  │  │    my_fps_game  │        │   my_rpg_game   │          │   │
│  │  └─────────────────┘        └─────────────────┘          │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Technical Stack

Core Technologies

Component Technology Notes
Language C++23 Modern C++ with modules support
Build System CMake 3.31+ With presets and modern features
Graphics API Vulkan Primary and only graphics backend
Windowing SDL3 Cross-platform window management
Editor UI Dear ImGui Immediate mode GUI for editor
ECS EnTT Entity Component System (or custom)
Physics Jolt Physics Primary physics engine (swappable via plugins)
Scripting Python 3.12+ Gameplay scripting with uv package manager

Scene & Asset Pipeline

Component Technology Notes
Scene Format glTF / OpenUSD Scene description and interchange
3D DCC Blender Primary 3D content creation, live connection
2D Image GIMP Photo editing and textures
2D Painting Krita Digital painting and texture creation
Vector Graphics Inkscape SVG and vector assets
Live Sync Omniverse-style Real-time DCC to engine connection

Note: GIMP vs Krita - They serve different purposes:

  • GIMP: Photo manipulation, compositing, texture editing
  • Krita: Digital painting, hand-painted textures, concept art

Networking & AI

Component Technology Notes
Networking Custom / ENet Online multiplayer support
AI/ML PyTorch / ONNX Machine Learning and Deep Learning integration
AI Runtime ONNX Runtime ML model inference in engine

Development Tools

Component Technology Notes
IDE/Editor VSCode / Neovim With custom plugins for engine integration
Profiling Tracy Real-time frame profiler
GPU Debug RenderDoc Graphics debugging and analysis
Code Analysis clang-tidy Static analysis
Formatting clang-format Code style enforcement

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                              AETHER ENGINE                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │                           EDITOR (ImGui)                            │    │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐   │    │
│  │  │ Viewport │ │ Hierarchy│ │Inspector │ │  Assets  │ │  Console │   │    │
│  │  └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘   │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │                         ENGINE CORE                                 │    │
│  │                                                                     │    │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌────────────┐  │    │
│  │  │    Core     │  │  Graphics   │  │    Audio    │  │  Scripting │  │    │
│  │  │             │  │   (Vulkan)  │  │             │  │  (Python)  │  │    │
│  │  │ - Types     │  │ - Renderer  │  │ - Playback  │  │ - Bindings │  │    │
│  │  │ - Memory    │  │ - Shaders   │  │ - 3D Sound  │  │ - Runtime  │  │    │
│  │  │ - Logger    │  │ - Materials │  │ - Mixer     │  │ - Hot-reload│ │    │
│  │  │ - Config    │  │ - Pipeline  │  │             │  │            │  │    │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  └────────────┘  │    │
│  │                                                                     │    │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌────────────┐  │    │
│  │  │  Physics    │  │     ECS     │  │   Network   │  │     AI     │  │    │
│  │  │   (Jolt)    │  │   (EnTT)    │  │             │  │   (ML/DL)  │  │    │
│  │  │             │  │             │  │ - Client    │  │            │  │    │
│  │  │ - Rigidbody │  │ - Entities  │  │ - Server    │  │ - ONNX     │  │    │
│  │  │ - Colliders │  │ - Components│  │ - Replicat° │  │ - PyTorch  │  │    │
│  │  │ - Queries   │  │ - Systems   │  │ - Lobbies   │  │ - Inference│  │    │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  └────────────┘  │    │
│  │                                                                     │    │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │    │
│  │  │  Resources  │  │    Input    │  │   Window    │                  │    │
│  │  │             │  │             │  │   (SDL3)    │                  │    │
│  │  │ - Loaders   │  │ - Keyboard  │  │             │                  │    │
│  │  │ - Caching   │  │ - Mouse     │  │ - Events    │                  │    │
│  │  │ - Streaming │  │ - Gamepad   │  │ - Context   │                  │    │
│  │  │ - glTF/USD  │  │ - Actions   │  │ - Vulkan    │                  │    │
│  │  └─────────────┘  └─────────────┘  └─────────────┘                  │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │                      EXTERNAL CONNECTIONS                           │    │
│  │                                                                     │    │
│  │  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌───────────┐         │    │
│  │  │  Blender  │  │   VSCode  │  │   Tracy   │  │ RenderDoc │         │    │
│  │  │  (Live)   │  │  (Plugin) │  │ (Profile) │  │  (Debug)  │         │    │
│  │  └───────────┘  └───────────┘  └───────────┘  └───────────┘         │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘

Directory Structure

AetherEngine/
│
├── 📁 sources/                      # All C++ source code
│   ├── engine/                      # Engine core
│   │   ├── core/                    # Types, memory, logging, config
│   │   │   ├── public/
│   │   │   │   └── aether/core/
│   │   │   ├── private/
│   │   │   └── CMakeLists.txt
│   │   ├── graphics/                # Vulkan renderer
│   │   ├── audio/                   # Audio system
│   │   ├── physics/                 # Physics interface (Jolt default)
│   │   ├── input/                   # Input handling
│   │   ├── scripting/               # Python integration
│   │   ├── resources/               # Asset loading (glTF, USD)
│   │   ├── ecs/                     # Entity Component System (EnTT wrapper)
│   │   ├── network/                 # Networking for online games
│   │   ├── ai/                      # AI/ML integration
│   │   ├── window/                  # SDL3 windowing
│   │   └── CMakeLists.txt
│   │
│   ├── editor/                      # Editor application (ImGui)
│   │   ├── public/
│   │   ├── private/
│   │   │   ├── panels/              # Editor panels (hierarchy, inspector...)
│   │   │   ├── widgets/             # Custom ImGui widgets
│   │   │   └── main.cpp
│   │   └── CMakeLists.txt
│   │
│   ├── runtime/                     # Game runtime executable
│   │   ├── private/
│   │   │   └── main.cpp
│   │   └── CMakeLists.txt
│   │
│   └── programs/                    # CLI tools
│       ├── asset_baker/             # Asset processing
│       ├── shader_compiler/         # SPIR-V compilation
│       └── scene_converter/         # glTF/USD conversion
│
├── 📁 plugins/                      # Technical engine extensions
│   ├── physics_jolt/                # Jolt Physics (default)
│   ├── physics_bullet/              # Bullet Physics alternative
│   ├── physics_physx/               # PhysX alternative
│   ├── audio_openal/                # OpenAL audio backend
│   ├── audio_fmod/                  # FMOD alternative
│   ├── ai_onnx/                     # ONNX Runtime for ML inference
│   └── ai_pytorch/                  # PyTorch integration
│
├── 📁 modules/                      # Reusable gameplay blocks
│   ├── fps_framework/               # First-person shooter mechanics
│   ├── tps_framework/               # Third-person mechanics
│   ├── inventory_system/            # Items, storage, equipment
│   ├── dialogue_system/             # Dialogues, choices, branching
│   ├── quest_system/                # Quests, objectives, rewards
│   ├── save_system/                 # Save/load game state
│   ├── multiplayer/                 # Online game framework
│   └── ai_behaviors/                # Common AI behaviors (FSM, BT, GOAP)
│
├── 📁 games/                        # Symlinks to external projects
│   ├── my_game -> ~/projects/my_game
│   └── .gitkeep
│
├── 📁 templates/                    # Project templates
│   ├── games/
│   │   ├── empty/                   # Minimal game
│   │   ├── fps/                     # FPS template
│   │   ├── platformer/              # 2D/3D platformer
│   │   ├── rpg/                     # RPG template
│   │   └── multiplayer/             # Online game template
│   └── modules/
│       └── empty/
│
├── 📁 runtimes/                     # Scripting environments
│   └── python/
│       ├── engine/                  # Base runtime environment
│       │   ├── pyproject.toml
│       │   └── uv.lock
│       └── dev/                     # Development environment
│           ├── pyproject.toml
│           └── uv.lock
│
├── 📁 extern/                       # Third-party dependencies (submodules)
│   ├── sdl3/                        # SDL3 windowing
│   ├── imgui/                       # Dear ImGui
│   ├── entt/                        # EnTT ECS
│   ├── jolt/                        # Jolt Physics
│   ├── glm/                         # Math library
│   ├── volk/                        # Vulkan loader
│   ├── vma/                         # Vulkan Memory Allocator
│   ├── tracy/                       # Profiler
│   ├── spdlog/                      # Logging
│   └── ...
│
├── 📁 cmake/                        # CMake modules and helpers
│   ├── helpers/
│   │   ├── AetherHelpers.cmake      # Game/Module helper functions
│   │   ├── ShaderCompilation.cmake  # SPIR-V compilation
│   │   └── ...
│   └── modules/
│       ├── FindVulkan.cmake
│       ├── FindSDL3.cmake
│       └── ...
│
├── 📁 configs/                      # Centralized configuration
│   ├── engine/
│   │   ├── engine.toml
│   │   └── graphics.toml
│   ├── editor/
│   │   └── editor.toml
│   └── dev/
│       └── debug.toml
│
├── 📁 assets/                       # Built-in engine assets
│   ├── shaders/                     # Built-in shaders
│   ├── fonts/                       # Default fonts
│   └── icons/                       # Editor icons
│
├── 📁 tests/                        # Unit and integration tests
│   ├── unit/
│   └── integration/
│
├── 📁 docs/                         # Documentation
│   ├── architecture/
│   ├── api/
│   └── guides/
│
├── 📁 scripts/                      # Utility scripts
│   ├── create_game.py
│   ├── create_module.py
│   ├── link_game.py
│   └── python_setup.py
│
├── 📁 tools/                        # External tool integrations
│   ├── blender/                     # Blender addon for live sync
│   ├── vscode/                      # VSCode extension
│   └── neovim/                      # Neovim plugin
│
├── CMakeLists.txt
├── CMakePresets.json
├── justfile
└── README.md

Core Concepts

Engine

The engine is the core of AetherEngine, providing all fundamental systems:

Module Technology Description
core - Types, memory, logging, config
graphics Vulkan Renderer, shaders, materials, pipeline
audio OpenAL/FMOD Audio playback, 3D sound, mixer
physics Jolt Physics simulation interface
input SDL3 Input handling, action mapping
scripting Python + pybind11 Python integration, hot-reload
resources glTF/OpenUSD Asset loading, serialization
ecs EnTT Entity Component System
network Custom Client/server, replication, lobbies
ai ONNX/PyTorch ML inference, behavior systems
window SDL3 Window management, Vulkan context

Engine Module Structure

sources/engine/core/
├── public/
│   └── aether/core/
│       ├── engine.hpp
│       ├── types.hpp
│       ├── memory.hpp
│       ├── logger.hpp
│       └── config.hpp
├── private/
│   ├── engine.cpp
│   ├── memory.cpp
│   ├── logger.cpp
│   └── config.cpp
└── CMakeLists.txt

CMakeLists.txt for Engine Module

add_library(AetherEngine_Core)
add_library(AetherEngine::Core ALIAS AetherEngine_Core)

target_sources(AetherEngine_Core
    PRIVATE
        private/engine.cpp
        private/memory.cpp
        private/logger.cpp
        private/config.cpp
    PUBLIC
        FILE_SET HEADERS
        BASE_DIRS public
        FILES
            public/aether/core/engine.hpp
            public/aether/core/types.hpp
            public/aether/core/memory.hpp
            public/aether/core/logger.hpp
            public/aether/core/config.hpp
)

target_include_directories(AetherEngine_Core
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public>
        $<INSTALL_INTERFACE:include>
)

target_link_libraries(AetherEngine_Core
    PUBLIC
        spdlog::spdlog
        glm::glm
    PRIVATE
        Tracy::TracyClient
)

target_compile_features(AetherEngine_Core PUBLIC cxx_std_23)

ECS Integration (EnTT)

// sources/engine/ecs/public/aether/ecs/world.hpp
#pragma once

#include <entt/entt.hpp>
#include <aether/core/types.hpp>

namespace aether {

/**
 * @brief Wrapper around EnTT registry providing a cleaner API.
 */
class World {
public:
    using Entity = entt::entity;
    
    Entity create_entity();
    void destroy_entity(Entity entity);
    
    template<typename T, typename... Args>
    T& add_component(Entity entity, Args&&... args) {
        return m_registry.emplace<T>(entity, std::forward<Args>(args)...);
    }
    
    template<typename T>
    T& get_component(Entity entity) {
        return m_registry.get<T>(entity);
    }
    
    template<typename T>
    bool has_component(Entity entity) const {
        return m_registry.any_of<T>(entity);
    }
    
    template<typename... Components>
    auto view() {
        return m_registry.view<Components...>();
    }
    
    entt::registry& registry() { return m_registry; }
    
private:
    entt::registry m_registry;
};

} // namespace aether

Physics Interface (Jolt)

// sources/engine/physics/public/aether/physics/physics_world.hpp
#pragma once

#include <aether/core/types.hpp>
#include <glm/glm.hpp>

namespace aether {

/**
 * @brief Abstract physics world interface.
 * 
 * This allows swapping physics backends via plugins
 * (Jolt, Bullet, PhysX).
 */
class IPhysicsWorld {
public:
    virtual ~IPhysicsWorld() = default;
    
    virtual void step(float delta_time) = 0;
    
    virtual BodyId create_rigid_body(const RigidBodyDesc& desc) = 0;
    virtual void destroy_rigid_body(BodyId id) = 0;
    
    virtual void set_linear_velocity(BodyId id, const glm::vec3& velocity) = 0;
    virtual glm::vec3 get_linear_velocity(BodyId id) const = 0;
    
    virtual void add_force(BodyId id, const glm::vec3& force) = 0;
    virtual void add_impulse(BodyId id, const glm::vec3& impulse) = 0;
    
    virtual RaycastResult raycast(const glm::vec3& origin, 
                                   const glm::vec3& direction,
                                   float max_distance) const = 0;
};

} // namespace aether

Plugins vs Modules

Aspect Plugin Module
Level Engine (technical) Gameplay (game logic)
Extends Engine capabilities Gameplay features
Used by Engine directly Games
Examples physics_jolt, audio_fmod, ai_onnx fps_framework, inventory_system
Loading At engine startup On game demand
Dependencies Engine core only Engine + other modules
Swappable Yes, via config Yes, games choose which to use

Plugin Examples

plugins/
├── physics_jolt/        # Jolt Physics (DEFAULT)
├── physics_bullet/      # Bullet Physics alternative
├── physics_physx/       # PhysX alternative
├── audio_openal/        # OpenAL audio backend
├── audio_fmod/          # FMOD alternative
├── ai_onnx/             # ONNX Runtime for ML inference
└── ai_pytorch/          # PyTorch C++ integration

Plugin Structure (physics_jolt)

plugins/physics_jolt/
├── sources/
│   ├── public/
│   │   └── aether/plugins/physics_jolt/
│   │       └── jolt_world.hpp
│   └── private/
│       ├── jolt_world.cpp
│       └── jolt_debug_renderer.cpp
├── CMakeLists.txt
└── README.md
// plugins/physics_jolt/sources/public/aether/plugins/physics_jolt/jolt_world.hpp
#pragma once

#include <aether/physics/physics_world.hpp>
#include <Jolt/Jolt.h>

namespace aether::plugins {

class JoltPhysicsWorld : public IPhysicsWorld {
public:
    JoltPhysicsWorld();
    ~JoltPhysicsWorld() override;
    
    void step(float delta_time) override;
    
    BodyId create_rigid_body(const RigidBodyDesc& desc) override;
    void destroy_rigid_body(BodyId id) override;
    
    // ... implementation of IPhysicsWorld interface
    
private:
    JPH::PhysicsSystem m_physics_system;
    // ... Jolt-specific members
};

} // namespace aether::plugins

// Plugin registration
AETHER_PLUGIN(JoltPhysicsWorld, "physics")

Module Examples

modules/
├── fps_framework/       # Weapons, characters, hitscan, damage
├── tps_framework/       # Third-person camera, cover system
├── inventory_system/    # Items, storage, equipment
├── dialogue_system/     # Dialogues, choices, branching
├── quest_system/        # Quests, objectives, rewards
├── save_system/         # Save/load game state
├── multiplayer/         # Networking framework for games
└── ai_behaviors/        # FSM, Behavior Trees, GOAP

Module Structure

modules/fps_framework/
├── sources/
│   ├── public/
│   │   └── fps_framework/
│   │       ├── weapon.hpp
│   │       ├── character.hpp
│   │       ├── hitscan.hpp
│   │       └── damage.hpp
│   ├── private/
│   │   ├── weapon.cpp
│   │   ├── character.cpp
│   │   ├── hitscan.cpp
│   │   └── damage.cpp
│   └── CMakeLists.txt
├── scripts/
│   ├── weapon_behavior.py
│   └── damage_system.py
├── assets/
│   └── effects/
└── CMakeLists.txt

Games

Games are separate repositories linked via symlinks in the games/ directory. This allows:

  • Independent versioning per game
  • Private repositories for games
  • Separate teams for engine vs gameplay
  • Selective cloning

Game Structure

~/projects/my_game/                  # Separate Git repository
│
├── 📁 sources/
│   └── game/
│       ├── public/
│       │   └── my_game/
│       │       ├── game.hpp
│       │       └── player.hpp
│       ├── private/
│       │   ├── game.cpp
│       │   └── player.cpp
│       └── CMakeLists.txt
│
├── 📁 scripts/                      # Python gameplay scripts
│   ├── behaviors/
│   │   └── player_controller.py
│   ├── systems/
│   │   └── combat.py
│   └── ui/
│       └── hud.py
│
├── 📁 assets/
│   ├── models/                      # glTF models
│   ├── textures/
│   ├── audio/
│   ├── levels/                      # Scene files (glTF/USD)
│   └── shaders/                     # Game-specific shaders
│
├── 📁 configs/
│   ├── game.toml
│   └── input.toml
│
├── 📁 runtimes/
│   └── python/
│       ├── pyproject.toml
│       └── uv.lock
│
├── CMakeLists.txt
└── README.md

Game Interface

// sources/engine/core/public/aether/core/game.hpp
#pragma once

#include <aether/core/types.hpp>
#include <aether/core/config.hpp>
#include <string>
#include <vector>

namespace aether {

class Engine;

class IGame {
public:
    virtual ~IGame() = default;

    // Lifecycle
    virtual void on_init(Engine& engine) = 0;
    virtual void on_shutdown() = 0;

    // Per-frame
    virtual void on_update(float delta_time) = 0;
    virtual void on_render() = 0;
    
    // Networking (optional)
    virtual void on_network_update() {}

    // Metadata
    virtual std::string get_name() const = 0;
    virtual std::string get_version() const = 0;
    virtual GameConfig get_config() const = 0;
};

struct GameConfig {
    std::string name;
    std::string version;
    std::vector<std::string> modules;
    std::vector<std::string> plugins;
    std::string scripts_path;
    std::string assets_path;
    
    // Networking
    bool is_multiplayer = false;
    NetworkConfig network;
};

} // namespace aether

#define AETHER_GAME(GameClass)                              \
    extern "C" {                                            \
        AETHER_EXPORT aether::IGame* create_game() {        \
            return new GameClass();                         \
        }                                                   \
        AETHER_EXPORT void destroy_game(aether::IGame* g) { \
            delete g;                                       \
        }                                                   \
    }

Game Implementation Example

// games/my_game/sources/game/public/my_game/game.hpp
#pragma once

#include <aether/core/game.hpp>

namespace my_game {

class Game final : public aether::IGame {
public:
    void on_init(aether::Engine& engine) override;
    void on_shutdown() override;
    void on_update(float delta_time) override;
    void on_render() override;

    std::string get_name() const override { return "My Awesome Game"; }
    std::string get_version() const override { return "0.1.0"; }
    aether::GameConfig get_config() const override;

private:
    aether::Engine* m_engine = nullptr;
    aether::World* m_world = nullptr;
};

} // namespace my_game
// games/my_game/sources/game/private/game.cpp
#include <my_game/game.hpp>
#include <aether/core/engine.hpp>
#include <aether/core/logger.hpp>
#include <aether/ecs/world.hpp>
#include <aether/scripting/python_runtime.hpp>
#include <aether/graphics/renderer.hpp>

// Modules
#include <fps_framework/character.hpp>
#include <fps_framework/weapon.hpp>
#include <inventory_system/inventory.hpp>

namespace my_game {

void Game::on_init(aether::Engine& engine) {
    m_engine = &engine;
    m_world = &engine.get<aether::World>();
    
    aether::Log::info("[MyGame] Initializing...");
    
    // Setup Python scripting
    auto& python = engine.get<aether::PythonRuntime>();
    python.add_script_path("games/my_game/scripts");
    python.load_module("behaviors.player_controller");
    
    // Create player entity
    auto player = m_world->create_entity();
    m_world->add_component<fps_framework::Character>(player);
    m_world->add_component<fps_framework::WeaponHolder>(player);
    m_world->add_component<inventory_system::Inventory>(player);
    
    // Load starting level
    engine.get<aether::SceneLoader>().load("assets/levels/start.gltf");
    
    aether::Log::info("[MyGame] Ready!");
}

void Game::on_shutdown() {
    aether::Log::info("[MyGame] Shutting down...");
}

void Game::on_update(float delta_time) {
    // Game systems run via ECS
}

void Game::on_render() {
    // Custom rendering if needed
}

aether::GameConfig Game::get_config() const {
    return {
        .name = "My Awesome Game",
        .version = "0.1.0",
        .modules = {"fps_framework", "inventory_system"},
        .plugins = {"physics_jolt"},
        .scripts_path = "scripts",
        .assets_path = "assets",
        .is_multiplayer = false
    };
}

} // namespace my_game

AETHER_GAME(my_game::Game)

Game Configuration

# games/my_game/configs/game.toml

[game]
name = "My Awesome Game"
version = "0.1.0"
entry_point = "my_game::Game"

[dependencies]
modules = ["fps_framework", "inventory_system"]
plugins = ["physics_jolt"]

[scripting]
scripts_path = "scripts"
main_script = "main.py"
use_game_env = true

[assets]
path = "assets"
scene_format = "gltf"  # or "usd"

[graphics]
# Vulkan-specific settings
vsync = true
msaa_samples = 4
hdr = true

[physics]
# Using Jolt via plugin
fixed_timestep = 0.016666  # 60 Hz
gravity = [0.0, -9.81, 0.0]

Python Integration

Environment Hierarchy

┌─────────────────────────────────────────────────────────────┐
│                    ENGINE (runtime)                         │
│  runtimes/python/engine/                                    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │ Dependencies:                                       │    │
│  │   - pybind11 (C++ bindings)                         │    │
│  │   - numpy (math operations)                         │    │
│  │   - tomli (config parsing)                          │    │
│  └─────────────────────────────────────────────────────┘    │
│                           │                                 │
│            ┌──────────────┴──────────────┐                  │
│            ▼                             ▼                  │
│  ┌─────────────────────┐    ┌─────────────────────────┐     │
│  │   DEV (development) │    │     GAME (per-game)     │     │
│  │ runtimes/python/dev │    │ games/x/runtimes/python │     │
│  │                     │    │                         │     │
│  │ Extends: engine     │    │ Extends: engine         │     │
│  │ + pytest            │    │ + game-specific deps    │     │
│  │ + ruff, black       │    │ + ML libraries          │     │
│  │ + sphinx, mypy      │    │                         │     │
│  └─────────────────────┘    └─────────────────────────┘     │
└─────────────────────────────────────────────────────────────┘

Engine Runtime Environment

# runtimes/python/engine/pyproject.toml

[project]
name = "aether-runtime"
version = "0.1.0"
description = "AetherEngine Python runtime environment"
requires-python = ">=3.12"

dependencies = [
    "pybind11>=2.12",
    "numpy>=2.0",
    "tomli>=2.0",
]

[tool.uv]
python = "3.12"

Development Environment

# runtimes/python/dev/pyproject.toml

[project]
name = "aether-dev"
version = "0.1.0"
description = "AetherEngine development environment"
requires-python = ">=3.12"

dependencies = []

[project.optional-dependencies]
dev = [
    # Testing
    "pytest>=8.0",
    "pytest-cov>=4.0",
    
    # Linting & Formatting
    "ruff>=0.4",
    "black>=24.0",
    "mypy>=1.10",
    
    # Documentation
    "sphinx>=7.0",
    "sphinx-rtd-theme>=2.0",
    
    # Debug
    "ipython>=8.0",
    "rich>=13.0",
]

ai = [
    # ML/DL development
    "torch>=2.0",
    "onnx>=1.15",
    "onnxruntime>=1.17",
]

[tool.uv]
python = "3.12"

[tool.uv.workspace]
members = ["../engine"]

Game Python Environment

# games/my_game/runtimes/python/pyproject.toml

[project]
name = "my_game-scripts"
version = "0.1.0"
description = "Python gameplay scripts for My Game"
requires-python = ">=3.12"

dependencies = [
    # Game-specific Python dependencies
    # "pillow>=10.0",  # Image processing
    # "pyyaml>=6.0",   # YAML configs
]

[project.optional-dependencies]
dev = [
    "pytest>=8.0",
    "ruff>=0.4",
]

ai = [
    # If game uses ML
    "onnxruntime>=1.17",
]

[tool.uv]
python = "3.12"

[tool.ruff]
line-length = 100
target-version = "py312"

Python Gameplay Script Example

# games/my_game/scripts/behaviors/player_controller.py

from aether.core import Component, Input, Vector3, Log
from aether.graphics import Transform
from aether.physics import Rigidbody
from fps_framework import Character, Weapon

class PlayerController(Component):
    """First-person player controller with full movement."""
    
    def __init__(self):
        super().__init__()
        self.move_speed = 5.0
        self.sprint_multiplier = 1.8
        self.jump_force = 8.0
        self.mouse_sensitivity = 0.3
        
    def on_start(self):
        self.transform = self.entity.get_component(Transform)
        self.character = self.entity.get_component(Character)
        self.rigidbody = self.entity.get_component(Rigidbody)
        self.current_weapon: Weapon | None = None
        
        # Lock cursor for FPS controls
        Input.set_cursor_mode("locked")
        Log.info("PlayerController initialized")
        
    def on_update(self, dt: float):
        self._handle_movement(dt)
        self._handle_look(dt)
        self._handle_combat()
        
    def _handle_movement(self, dt: float):
        direction = Vector3.zero()
        
        if Input.is_action_pressed("move_forward"):
            direction.z += 1
        if Input.is_action_pressed("move_backward"):
            direction.z -= 1
        if Input.is_action_pressed("move_left"):
            direction.x -= 1
        if Input.is_action_pressed("move_right"):
            direction.x += 1
            
        speed = self.move_speed
        if Input.is_action_pressed("sprint") and self.character.stamina > 0:
            speed *= self.sprint_multiplier
            self.character.use_stamina(dt * 10)
            
        if direction.length_squared() > 0:
            direction = self.transform.transform_direction(direction.normalized())
            self.character.move(direction * speed * dt)
            
        if Input.is_action_just_pressed("jump") and self.character.is_grounded:
            self.rigidbody.add_impulse(Vector3(0, self.jump_force, 0))
            
    def _handle_look(self, dt: float):
        look_x = Input.get_axis("look_horizontal") * self.mouse_sensitivity
        look_y = Input.get_axis("look_vertical") * self.mouse_sensitivity
        self.character.rotate_view(look_x, look_y)
        
    def _handle_combat(self):
        if self.current_weapon is None:
            return
            
        if Input.is_action_pressed("fire"):
            self.current_weapon.fire()
        if Input.is_action_just_pressed("reload"):
            self.current_weapon.reload()
        if Input.is_action_just_pressed("aim"):
            self.current_weapon.start_aim()
        if Input.is_action_just_released("aim"):
            self.current_weapon.stop_aim()

AI/ML Python Integration Example

# games/my_game/scripts/ai/enemy_brain.py

from aether.core import Component, Vector3, Log
from aether.ai import ONNXModel
import numpy as np

class EnemyBrain(Component):
    """Neural network-driven enemy AI."""
    
    def __init__(self, model_path: str = "assets/models/enemy_ai.onnx"):
        super().__init__()
        self.model = ONNXModel(model_path)
        self.decision_interval = 0.1  # 10 Hz decision making
        self.time_since_decision = 0.0
        
    def on_start(self):
        self.transform = self.entity.get_component("Transform")
        self.character = self.entity.get_component("Character")
        Log.info(f"EnemyBrain loaded model: {self.model.path}")
        
    def on_update(self, dt: float):
        self.time_since_decision += dt
        
        if self.time_since_decision >= self.decision_interval:
            self.time_since_decision = 0.0
            self._make_decision()
            
    def _make_decision(self):
        # Gather observations
        obs = self._get_observations()
        
        # Run inference
        action = self.model.predict(obs)
        
        # Execute action
        self._execute_action(action)
        
    def _get_observations(self) -> np.ndarray:
        """Gather world state for the neural network."""
        player = self.world.find_entity_by_tag("Player")
        if player is None:
            return np.zeros(10)
            
        player_pos = player.get_component("Transform").position
        my_pos = self.transform.position
        
        direction_to_player = (player_pos - my_pos).normalized()
        distance = (player_pos - my_pos).length()
        
        return np.array([
            direction_to_player.x,
            direction_to_player.y,
            direction_to_player.z,
            distance / 50.0,  # Normalized distance
            self.character.health / 100.0,
            self.character.ammo / 30.0,
            float(self.character.is_in_cover),
            float(self.character.can_see_player),
            # ... more observations
        ], dtype=np.float32)
        
    def _execute_action(self, action: np.ndarray):
        """Execute the action chosen by the neural network."""
        action_id = int(np.argmax(action))
        
        match action_id:
            case 0:
                self.character.move_towards_player()
            case 1:
                self.character.take_cover()
            case 2:
                self.character.fire_at_player()
            case 3:
                self.character.reload()
            case 4:
                self.character.flank()

External Tools Integration

Blender Live Sync

The engine provides a Blender addon for real-time synchronization:

tools/blender/
├── aether_sync/
│   ├── __init__.py
│   ├── operators.py
│   ├── panels.py
│   ├── sync_client.py
│   └── export_utils.py
└── README.md
# tools/blender/aether_sync/__init__.py

bl_info = {
    "name": "AetherEngine Sync",
    "author": "AIperture Labs",
    "version": (0, 1, 0),
    "blender": (4, 0, 0),
    "category": "Import-Export",
    "description": "Real-time sync with AetherEngine",
}

import bpy
from .operators import AETHER_OT_connect, AETHER_OT_sync_scene
from .panels import AETHER_PT_main_panel

classes = [
    AETHER_OT_connect,
    AETHER_OT_sync_scene,
    AETHER_PT_main_panel,
]

def register():
    for cls in classes:
        bpy.utils.register_class(cls)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)

VSCode Extension

tools/vscode/
├── package.json
├── src/
│   ├── extension.ts
│   ├── engine_connection.ts
│   └── script_hot_reload.ts
└── README.md
// tools/vscode/package.json
{
    "name": "aether-engine",
    "displayName": "AetherEngine",
    "description": "AetherEngine development tools for VSCode",
    "version": "0.1.0",
    "engines": {
        "vscode": "^1.85.0"
    },
    "categories": ["Other"],
    "activationEvents": [
        "workspaceContains:**/configs/game.toml"
    ],
    "main": "./out/extension.js",
    "contributes": {
        "commands": [
            {
                "command": "aether.connectEngine",
                "title": "AetherEngine: Connect to Running Instance"
            },
            {
                "command": "aether.hotReloadScript",
                "title": "AetherEngine: Hot Reload Current Script"
            }
        ]
    }
}

Tracy Profiler Integration

// sources/engine/core/public/aether/core/profiler.hpp
#pragma once

#include <tracy/Tracy.hpp>

// Profiling macros
#define AETHER_PROFILE_SCOPE(name) ZoneScopedN(name)
#define AETHER_PROFILE_FUNCTION() ZoneScoped
#define AETHER_PROFILE_FRAME() FrameMark

// GPU profiling (Vulkan)
#define AETHER_PROFILE_GPU_SCOPE(ctx, name) TracyVkZone(ctx, name)
// Usage example
void Renderer::render(const Scene& scene) {
    AETHER_PROFILE_FUNCTION();
    
    {
        AETHER_PROFILE_SCOPE("Shadow Pass");
        render_shadows(scene);
    }
    
    {
        AETHER_PROFILE_SCOPE("Main Pass");
        render_main(scene);
    }
    
    {
        AETHER_PROFILE_SCOPE("Post Process");
        apply_post_process();
    }
    
    AETHER_PROFILE_FRAME();
}

RenderDoc Integration

// sources/engine/graphics/private/renderdoc_integration.cpp
#include <aether/graphics/debug.hpp>

#ifdef AETHER_ENABLE_RENDERDOC
#include <renderdoc_app.h>

namespace aether {

class RenderDocCapture {
public:
    static void init() {
        if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) {
            pRENDERDOC_GetAPI getApi;
            getApi = (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
            getApi(eRENDERDOC_API_Version_1_1_2, (void**)&s_api);
        }
    }
    
    static void begin_capture() {
        if (s_api) s_api->StartFrameCapture(nullptr, nullptr);
    }
    
    static void end_capture() {
        if (s_api) s_api->EndFrameCapture(nullptr, nullptr);
    }
    
private:
    static inline RENDERDOC_API_1_1_2* s_api = nullptr;
};

} // namespace aether
#endif

Templates

Creating a New Game

# Using the helper script
python scripts/create_game.py my_fps_game --template fps --path ~/projects

# Or using justfile
just games-create my_fps_game fps ~/projects

Available Templates

Template Description Includes Modules
empty Minimal game setup None
fps First-person shooter fps_framework
platformer 2D/3D platformer -
rpg Role-playing game inventory_system, dialogue_system, quest_system
multiplayer Online multiplayer multiplayer

Template Structure (FPS)

templates/games/fps/
├── sources/
│   └── game/
│       ├── public/
│       │   └── {{game_name}}/
│       │       ├── game.hpp
│       │       └── player.hpp
│       ├── private/
│       │   ├── game.cpp
│       │   └── player.cpp
│       └── CMakeLists.txt
├── scripts/
│   ├── behaviors/
│   │   ├── player_controller.py
│   │   └── enemy_ai.py
│   ├── systems/
│   │   └── damage_system.py
│   └── ui/
│       └── hud.py
├── assets/
│   ├── models/
│   ├── textures/
│   ├── audio/
│   │   ├── weapons/
│   │   └── ambient/
│   └── levels/
├── configs/
│   ├── game.toml.in
│   ├── input.toml
│   └── weapons.toml
├── runtimes/
│   └── python/
│       └── pyproject.toml.in
├── CMakeLists.txt.in
└── README.md.in

Game Creation Script

#!/usr/bin/env python3
# scripts/create_game.py

import argparse
import os
import shutil
from pathlib import Path

TEMPLATES_DIR = Path(__file__).parent.parent / "templates" / "games"
GAMES_DIR = Path(__file__).parent.parent / "games"

def get_available_templates() -> list[str]:
    return [d.name for d in TEMPLATES_DIR.iterdir() if d.is_dir()]

def to_pascal_case(name: str) -> str:
    return "".join(word.capitalize() for word in name.split("_"))

def to_namespace(name: str) -> str:
    return name.lower().replace("-", "_")

def create_game(
    name: str,
    template: str,
    output_path: Path,
    display_name: str | None = None,
    version: str = "0.1.0",
    link: bool = True,
) -> Path:
    
    template_path = TEMPLATES_DIR / template
    if not template_path.exists():
        raise ValueError(f"Template '{template}' not found. Available: {get_available_templates()}")
    
    game_path = output_path / name
    if game_path.exists():
        raise ValueError(f"Directory already exists: {game_path}")
    
    variables = {
        "{{game_name}}": name,
        "{{game_namespace}}": to_namespace(name),
        "{{game_display_name}}": display_name or to_pascal_case(name),
        "{{game_version}}": version,
        "{{game_modules}}": "",
    }
    
    print(f"Creating game '{name}' from template '{template}'...")
    print(f"  Output: {game_path}")
    
    shutil.copytree(template_path, game_path)
    
    # Process template files
    for root, dirs, files in os.walk(game_path):
        root_path = Path(root)
        
        # Rename directories
        for dir_name in dirs:
            if "{{" in dir_name:
                old_path = root_path / dir_name
                new_name = dir_name
                for var, value in variables.items():
                    new_name = new_name.replace(var, value)
                old_path.rename(root_path / new_name)
        
        # Process files
        for file_name in files:
            file_path = root_path / file_name
            if file_path.suffix in [".png", ".jpg", ".wav", ".ogg", ".gltf", ".glb"]:
                continue
            
            new_file_name = file_name
            for var, value in variables.items():
                new_file_name = new_file_name.replace(var, value)
            
            if new_file_name.endswith(".in"):
                new_file_name = new_file_name[:-3]
            
            try:
                content = file_path.read_text()
                for var, value in variables.items():
                    content = content.replace(var, value)
                
                new_file_path = file_path.parent / new_file_name
                new_file_path.write_text(content)
                
                if file_path != new_file_path:
                    file_path.unlink()
            except UnicodeDecodeError:
                if file_name != new_file_name:
                    file_path.rename(file_path.parent / new_file_name)
    
    # Initialize git
    os.system(f"cd {game_path} && git init")
    print(f"  ✓ Game created: {game_path}")
    
    if link:
        link_game(name, game_path)
    
    return game_path

def link_game(name: str, game_path: Path):
    symlink_path = GAMES_DIR / name
    
    if symlink_path.exists():
        if symlink_path.is_symlink():
            symlink_path.unlink()
        else:
            raise ValueError(f"Cannot create symlink: {symlink_path} exists")
    
    symlink_path.symlink_to(game_path.resolve())
    print(f"  ✓ Symlink created: {symlink_path} -> {game_path}")

def main():
    parser = argparse.ArgumentParser(description="Create a new game from template")
    parser.add_argument("name", help="Game name (snake_case)")
    parser.add_argument("--template", "-t", default="empty", choices=get_available_templates())
    parser.add_argument("--path", "-p", type=Path, default=Path.home() / "projects")
    parser.add_argument("--display-name", "-d")
    parser.add_argument("--version", "-v", default="0.1.0")
    parser.add_argument("--no-link", action="store_true")
    
    args = parser.parse_args()
    create_game(
        name=args.name,
        template=args.template,
        output_path=args.path,
        display_name=args.display_name,
        version=args.version,
        link=not args.no_link,
    )

if __name__ == "__main__":
    main()

CMake Configuration

Root CMakeLists.txt

cmake_minimum_required(VERSION 3.31...4.1)

project(
    AetherEngine
    VERSION 0.1.0
    LANGUAGES C CXX
)

# ============================================================================
# CMake Configuration
# ============================================================================
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/helpers")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")

include(CompilerWarnings)
include(CompileCommandsSymlink)
include(Config)
include(Dependencies)
include(AetherHelpers)

# ============================================================================
# Options
# ============================================================================
option(AETHER_BUILD_EDITOR "Build the Editor" ON)
option(AETHER_BUILD_PROGRAMS "Build CLI tools" ON)
option(AETHER_BUILD_TESTS "Build tests" OFF)
option(AETHER_BUILD_DOCS "Build documentation" OFF)

# Profiling
option(AETHER_ENABLE_TRACY "Enable Tracy profiler" ON)
option(AETHER_ENABLE_RENDERDOC "Enable RenderDoc integration" ON)

set(AETHER_ACTIVE_GAME "" CACHE STRING "Game to build (empty = all)")

# ============================================================================
# External Dependencies
# ============================================================================
find_package(Vulkan REQUIRED)
find_package(SDL3 REQUIRED)
find_package(EnTT REQUIRED)
find_package(glm REQUIRED)

if(AETHER_ENABLE_TRACY)
    find_package(Tracy REQUIRED)
endif()

# ============================================================================
# Build Targets
# ============================================================================
add_subdirectory(sources/engine)
add_subdirectory(plugins)
add_subdirectory(modules)
add_subdirectory(games)
add_subdirectory(sources/runtime)

if(AETHER_BUILD_EDITOR)
    find_package(imgui REQUIRED)
    add_subdirectory(sources/editor)
endif()

if(AETHER_BUILD_PROGRAMS)
    add_subdirectory(sources/programs)
endif()

if(AETHER_BUILD_TESTS)
    enable_testing()
    add_subdirectory(tests)
endif()

if(AETHER_BUILD_DOCS)
    add_subdirectory(docs)
endif()

Engine CMakeLists.txt

# sources/engine/CMakeLists.txt

add_subdirectory(core)
add_subdirectory(window)      # SDL3
add_subdirectory(graphics)    # Vulkan
add_subdirectory(audio)
add_subdirectory(physics)
add_subdirectory(input)
add_subdirectory(scripting)   # Python
add_subdirectory(resources)   # glTF/USD
add_subdirectory(ecs)         # EnTT
add_subdirectory(network)
add_subdirectory(ai)

# Aggregate library
add_library(AetherEngine INTERFACE)
add_library(AetherEngine::Engine ALIAS AetherEngine)

target_link_libraries(AetherEngine
    INTERFACE
        AetherEngine::Core
        AetherEngine::Window
        AetherEngine::Graphics
        AetherEngine::Audio
        AetherEngine::Physics
        AetherEngine::Input
        AetherEngine::Scripting
        AetherEngine::Resources
        AetherEngine::ECS
        AetherEngine::Network
        AetherEngine::AI
)

CMake Helper Functions