Skip to main content

helios/engine/ecs/README.md File

Namespaces Index

namespaceecs

Core Entity-Component-System architecture. More...

File Listing

The file content with the documentation metadata removed is:

 # helios::engine::ecs
 
 Core Entity-Component-System architecture for the helios game engine.
 
 ## Overview
 
 This module provides the foundational classes for the composition-based game architecture. It separates data (Components) from behavior (Systems). Entity lifecycle and world management are provided by `helios.engine.runtime.world`.
 
 ## Key Classes
 
 | Class | Purpose |
 |-------|---------|
 | `GameObject` | Lightweight entity facade (~16 bytes, pass-by-value) |
 | `EntityHandle` | Versioned handle for safe entity references (8 bytes) |
 | `EntityRegistry` | Handle allocation and validation |
 | `EntityManager` | Unified interface for entity creation and component storage |
 | `SparseSet<T>` | Generic O(1) data structure for component storage |
 | `SparseSetBase` | Type-erased base for polymorphic sparse set access |
 | `View` | Component-based entity queries |
 | `System` | Abstract base for logic processors |
 | `Updatable` | Interface for per-frame updatable objects |
 | `ComponentOps` | Function pointers for lifecycle callbacks |
 | `ComponentOpsRegistry` | Global registry mapping type IDs to ComponentOps |
 | `ComponentReflector` | Compile-time type registration |
 | `Traits` | Compile-time concepts for component lifecycle hooks |
 
 ## Component Storage Model
 
 `GameObject` uses a **type-indexed storage** system for components. Instead of a hash-based lookup, components are stored in a contiguous vector where the index corresponds to the component's compile-time `ComponentTypeId`.
 
 **Performance Characteristics:**
 
 | Operation | Complexity | Notes |
 |-----------|------------|-------|
 | `get<T>()` | O(1) | Direct array access via type ID |
 | `has<T>()` | O(1) | Bounds check + nullptr check |
 | `add<T>()` | O(1) amortized | May trigger resize if type ID exceeds capacity |
 | `components()` | O(1) / O(n) | O(1) if cache valid, O(n) on first access after modification |
 
 **Trade-offs:**
 - **Memory**: Sparse vector with nullptr slots for unused component types.
 - **Speed**: Direct indexing without hash computation or collision handling.
 - **Cache**: Filtered component views are cached and lazily rebuilt.
 
 ```cpp
 // Storage layout example (conceptual):
 // Index: [0] [1] [2] [3] ...
 // Content: nullptr Transform nullptr Move2D ...
 // ↑ ↑
 // ComponentTypeId::id<Transform>() ComponentTypeId::id<Move2D>()
 ```
 
 ## EntityRegistry and EntityManager
 
 The **EntityRegistry** is the single source of truth for entity lifecycle. It manages handle allocation, version tracking, and entity validation.
 
 The **EntityManager** provides a high-level API combining registry and component storage:
 
 ```cpp
 EntityRegistry registry;
 EntityManager manager(registry);
 
 // Create entity
 auto entity = manager.create();
 
 // Attach components
 auto* transform = manager.emplace<TransformComponent>(entity, glm::vec3{0.0f});
 auto* velocity = manager.emplace<VelocityComponent>(entity);
 
 // Check and retrieve component
 if (manager.has<TransformComponent>(entity)) {
  auto* t = manager.get<TransformComponent>(entity);
 }
 
 // Remove single component
 manager.remove<TransformComponent>(entity);
 
 // Destroy entity (removes all components and invalidates handle)
 manager.destroy(entity);
 ```
 
 **Architecture:**
 
 ```
 ┌────────────────────────────────────────────────────────────┐
 │ EntityManager │
 │ ┌──────────────────┐ ┌───────────────────────────────┐ │
 │ │ EntityRegistry │ │ Component Storage │ │
 │ │ (handle mgmt) │ │ vector<SparseSet<T>> │ │
 │ │ - create() │ │ (indexed by TypeIndexer) │ │
 │ │ - destroy() │ │ │ │
 │ │ - isValid() │ │ [0] SparseSet<Transform> │ │
 │ └──────────────────┘ │ [1] SparseSet<Velocity> │ │
 │ │ [2] SparseSet<Health> │ │
 │ └───────────────────────────────┘ │
 └────────────────────────────────────────────────────────────┘
 ```
 
 ## EntityPool
 
 `EntityPool<T>` is a sparse-set based data structure for storing entities with versioned handles. It provides O(1) insertion, lookup, and cache-friendly iteration.
 
 **Data Structure:**
 
 ```
 sparse_: [0] [1] [2] [3] ... (maps entity ID → dense index)
  ↓ ↓ ↓ ↓
 dense_: [0] [2] [3] ... (entity IDs, contiguous)
 denseData_: [E0] [E2] [E3] ... (actual entities, cache-friendly)
 version_: [1] [1] [2] [1] ... (version per ID, incremented on removal)
 ```
 
 
 **Versioned Handles:**
 
 `EntityHandle` contains both an entity ID and a version number. When an entity is removed, its version is incremented. This allows detection of stale handles that reference deleted entities.
 
 ```cpp
 // EntityPool usage example
 EntityPool<GameObject> pool;
 
 // Add entity, receive handle
 auto handle = pool.emplace(std::make_unique<GameObject>());
 
 // Retrieve entity via handle (O(1))
 auto* entity = pool.get(handle);
 
 // Iterate all entities (cache-friendly)
 for (auto& e : pool.entities()) {
  // process entity
 }
 ```
 
 ## Submodules
 
 ### Traits
 
 Compile-time concepts for component lifecycle hooks:
 
 | Trait | Purpose |
 |-------|---------|
 | `HasOnRemove` | Intercept removal (return `false` to cancel) |
 | `HasOnAcquire` | Called when acquired from a pool |
 | `HasOnRelease` | Called when released back to a pool |
 
 ```cpp
 struct ResourceComponent {
  bool onRemove() {
  cleanup();
  return true; // Allow removal
  }
 };
 
 static_assert(helios::engine::ecs::traits::HasOnRemove<ResourceComponent>);
 ```
 
 ### query/
 
 Entity query utilities for filtering and iterating GameObjects:
 
 | Class | Purpose |
 |-------|---------|
 | `GameObjectFilter` | Bitmask for filtering by active/enabled state |
 | `GameObjectView` | Lazy range for component-based iteration |
 
 ## Related Modules
 
 | Module | Purpose |
 |--------|---------|
 | `helios.engine.runtime.world` | GameWorld, Level, UpdateContext, Manager, SystemRegistry |
 | `helios.engine.runtime.gameloop` | GameLoop, Phase, Pass |
 
 ## Architecture
 
 ```
 ┌─────────────────────────────────────────────────────────────┐
 │ GameWorld │
 │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
 │ │ GameObjects │ │ Managers │ │ Pools/Registry │ │
 │ │ (entities) │ │ (deferred) │ │ (object recycling) │ │
 │ └─────────────┘ └─────────────┘ └─────────────────────┘ │
 └─────────────────────────────────────────────────────────────┘
  │ │
  ▼ ▼
 ┌─────────────────────────────────────────────────────────────┐
 │ GameLoop │
 │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
 │ │ Pre │─>│ Main │─>│ Post │ (Phases) │
 │ │ Phase │ │ Phase │ │ Phase │ │
 │ └─────────┘ └─────────┘ └─────────┘ │
 │ │ │ │ │
 │ ▼ ▼ ▼ │
 │ Systems Systems Systems (execute in order) │
 └─────────────────────────────────────────────────────────────┘
 ```
 
 ## Usage Example
 
 ```cpp
 import helios.engine.ecs;
 import helios.engine.runtime.world.GameWorld;
 
 // Create game world
 helios::engine::runtime::world::GameWorld world;
 
 // Add entity with components
 auto entity = std::make_unique<helios::engine::ecs::GameObject>();
 entity.add<Move2DComponent>();
 entity.add<SceneNodeComponent>(sceneNode);
 auto* player = world.addGameObject(std::move(entity));
 
 // Query entities by component
 for (auto [obj, move] : world.find<Move2DComponent>()) {
  // Process matching entities
 }
 ```
 
 ---
 
 <details>
 <summary>Doxygen</summary><p>
 @namespace helios::engine::ecs
 @brief Core Entity-Component-System architecture.
 @details This module provides the foundational classes for the composition-based game architecture. It includes entity base classes (GameObject, Component, CloneableComponent), system infrastructure (System), and query utilities (GameObjectFilter, GameObjectView).
 </p></details>
 

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.