JustAnotherDnDGame 0.1.0
Jeu de rôle tactique au d20, vue de dessus, en C++/Qt
Loading...
Searching...
No Matches
ComponentPool.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Valentin Eloy
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <cstddef>
7#include <vector>
8
10#include "Core/Ecs/Entity.h"
11
16
17namespace core {
18
27public:
28 virtual ~IComponentPool() = default;
29
35 virtual bool removeIfPresent(Entity entity) = 0;
36};
37
60template <typename T>
62public:
64 static constexpr std::size_t INVALID_POSITION = ~std::size_t{0};
65
72 void add(Entity entity, const T& component) {
73 JADG_ASSERT(!has(entity), "L'entite possede deja ce composant.");
74
75 ensureSparseSize(entity.index);
76 _sparse[entity.index] = _components.size();
77 _components.push_back(component);
78 _entities.push_back(entity);
79 }
80
86 void remove(Entity entity) {
87 JADG_ASSERT(has(entity), "L'entite ne possede pas ce composant.");
88
89 const std::size_t removed = _sparse[entity.index];
90 const std::size_t last = _components.size() - 1;
91
92 // Swap-and-pop : on remonte le dernier élément à la place du supprimé
93 // pour garder le tableau dense contigu, puis on met à jour le creux de
94 // l'entité déplacée pour qu'il pointe vers sa nouvelle position.
95 _components[removed] = _components[last];
96 _entities[removed] = _entities[last];
97 _sparse[_entities[removed].index] = removed;
98
99 _components.pop_back();
100 _entities.pop_back();
102 }
103
109 bool removeIfPresent(Entity entity) override {
110 if (!has(entity)) {
111 return false;
112 }
113 remove(entity);
114 return true;
115 }
116
122 [[nodiscard]] bool has(Entity entity) const {
123 if (entity.index >= _sparse.size()) {
124 return false;
125 }
126 const std::size_t position = _sparse[entity.index];
127 // Position valide et pointant une entrée dont l'entité correspond
128 // exactement (l'égalité inclut la génération : un handle périmé échoue).
129 return position != INVALID_POSITION && _entities[position] == entity;
130 }
131
138 [[nodiscard]] T& get(Entity entity) {
139 JADG_ASSERT(has(entity), "L'entite ne possede pas ce composant.");
140 return _components[_sparse[entity.index]];
141 }
142
149 [[nodiscard]] const T& get(Entity entity) const {
150 JADG_ASSERT(has(entity), "L'entite ne possede pas ce composant.");
151 return _components[_sparse[entity.index]];
152 }
153
155 [[nodiscard]] std::size_t size() const {
156 return _components.size();
157 }
158
160 [[nodiscard]] bool empty() const {
161 return _components.empty();
162 }
163
168 [[nodiscard]] const std::vector<Entity>& entities() const {
169 return _entities;
170 }
171
176 [[nodiscard]] const std::vector<T>& components() const {
177 return _components;
178 }
179
180private:
186 if (index >= _sparse.size()) {
187 _sparse.resize(static_cast<std::size_t>(index) + 1, INVALID_POSITION);
188 }
189 }
190
192 std::vector<T> _components;
194 std::vector<Entity> _entities;
196 std::vector<std::size_t> _sparse;
197};
198
199} // namespace core
Assertions du projet : vérifient préconditions et invariants (bugs).
#define JADG_ASSERT(condition, message)
Vérifie une précondition.
Definition Assert.h:47
Identifiant d'entité de l'ECS : handle générationnel (index + génération).
Stockage dense des composants d'un type T, indexé par entité (sparse set).
Definition ComponentPool.h:61
static constexpr std::size_t INVALID_POSITION
Position dense réservée signifiant « aucun composant pour cette entité ».
Definition ComponentPool.h:64
void ensureSparseSize(Entity::Index index)
Agrandit le tableau creux pour qu'il couvre un index d'entité donné.
Definition ComponentPool.h:185
std::vector< Entity > _entities
Entités propriétaires, parallèle à _components.
Definition ComponentPool.h:194
const T & get(Entity entity) const
Accède au composant d'une entité (lecture seule).
Definition ComponentPool.h:149
const std::vector< T > & components() const
Composants stockés, dans l'ordre du tableau dense.
Definition ComponentPool.h:176
std::vector< std::size_t > _sparse
Position dense de chaque entité, indexé par Entity::index (INVALID_POSITION si absente).
Definition ComponentPool.h:196
const std::vector< Entity > & entities() const
Entités possédant un composant, dans l'ordre du tableau dense.
Definition ComponentPool.h:168
std::vector< T > _components
Tableau dense des composants (contigu, cache-friendly).
Definition ComponentPool.h:192
T & get(Entity entity)
Accède au composant d'une entité (lecture-écriture).
Definition ComponentPool.h:138
bool empty() const
Definition ComponentPool.h:160
std::size_t size() const
Definition ComponentPool.h:155
void add(Entity entity, const T &component)
Attache un composant à une entité.
Definition ComponentPool.h:72
bool has(Entity entity) const
Indique si une entité possède un composant de ce type.
Definition ComponentPool.h:122
void remove(Entity entity)
Retire le composant d'une entité (swap-and-pop).
Definition ComponentPool.h:86
bool removeIfPresent(Entity entity) override
Retire le composant d'une entité s'il existe (sans précondition).
Definition ComponentPool.h:109
Interface type-effacée d'une pool de composants.
Definition ComponentPool.h:26
virtual ~IComponentPool()=default
virtual bool removeIfPresent(Entity entity)=0
Retire le composant d'une entité s'il existe.
Espace de noms du moteur et de la logique de jeu.
Definition Bootstrap.h:9
Handle générationnel identifiant une entité de l'ECS.
Definition Entity.h:24
Index index
Definition Entity.h:33
std::uint32_t Index
Type des index d'entité.
Definition Entity.h:26