ToyMaker Game Engine 0.0.2
ToyMaker is a game engine developed and maintained by Zoheb Shujauddin.
Loading...
Searching...
No Matches
ecs_world.hpp
Go to the documentation of this file.
1
13
14#ifndef TOYMAKERENGINE_ECSWORLD_H
15#define TOYMAKERENGINE_ECSWORLD_H
16
17#include <iostream>
18#include <chrono>
19#include <cstdint>
20#include <typeinfo>
21#include <tuple>
22#include <memory>
23#include <vector>
24#include <set>
25#include <bitset>
26#include <unordered_map>
27#include <set>
28
29#include <nlohmann/json.hpp>
30
31#include "../util.hpp"
32#include "../registrator.hpp"
33
39
45
51
57
58namespace ToyMaker {
59
60
61
68 using EntityID = std::uint64_t;
69
76 using WorldID = std::uint64_t;
77
85 using UniversalEntityID = std::pair<WorldID, EntityID>;
86
93 using ECSType = std::uint8_t;
94
104
113
119 constexpr EntityID kMaxEntities { 1000000 };
120
125 constexpr ECSType kMaxECSTypes { 255 };
126
133
140
154 using Signature = std::bitset<kMaxComponents>;
155
156 class BaseSystem;
157 class SystemManager;
158 class ComponentManager;
159 class Entity;
160 class ECSWorld;
161
169 public:
170
176 explicit BaseComponentArray(std::weak_ptr<ECSWorld> world): mWorld{world} {}
177
182 virtual ~BaseComponentArray()=default;
183
189 virtual void handleEntityDestroyed(EntityID entityID)=0;
190
197 virtual void handlePreSimulationStep() = 0;
198
205 virtual void copyComponent(EntityID to, EntityID from)=0;
206
214 virtual void copyComponent(EntityID to, EntityID from, BaseComponentArray& other) = 0;
215
222 virtual void addComponent(EntityID to, const nlohmann::json& jsonComponent)=0;
223
230 virtual void updateComponent(EntityID to, const nlohmann::json& jsonComponent)=0;
231
239 virtual bool hasComponent(EntityID entityID) const=0;
240
246 virtual void removeComponent(EntityID entityID)=0;
247
254 virtual std::shared_ptr<BaseComponentArray> instantiate(std::weak_ptr<ECSWorld> world) const = 0;
255
256 protected:
257
262 std::weak_ptr<ECSWorld> mWorld {};
263 };
264
288 template <typename TComponent, typename Enable=void>
296 static TComponent get(const nlohmann::json& jsonComponent){
297 // in the regular case, just invoke the from_json method that the
298 // author of the component has presumably implemented
299 TComponent component = jsonComponent;
300 return component;
301 }
302 };
303
314 template <typename TComponent, typename Enable>
315 struct ComponentFromJSON<std::shared_ptr<TComponent>, Enable> {
316 static std::shared_ptr<TComponent> get(const nlohmann::json& jsonComponent) {
317 // assume once again that the author of the component has provided
318 // a from_json function that will be invoked here
319 std::shared_ptr<TComponent> component { new TComponent{} = jsonComponent };
320 return component;
321 }
322 };
323
336 template<typename T>
338 public:
347 T operator() (const T& previousState, const T& nextState, float simulationProgress=1.f) const;
348
349 private:
354 RangeMapperLinear mProgressLimits {0.f, 1.f, 0.f, 1.f};
355 };
356
365 template<typename TComponent>
367 public:
373 explicit ComponentArray(std::weak_ptr<ECSWorld> world): BaseComponentArray{ world } {}
374
375 private:
376
383 std::shared_ptr<BaseComponentArray> instantiate(std::weak_ptr<ECSWorld> world) const override;
384
391 void addComponent(EntityID entityID, const TComponent& component);
392
399 void addComponent(EntityID entityID, const nlohmann::json& componentJSON) override;
400
406 void removeComponent(EntityID entityID) override;
407
415 TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const;
416
426 bool hasComponent(EntityID entityID) const override;
427
434 void updateComponent(EntityID entityID, const TComponent& newValue);
435
442 void updateComponent(EntityID entityID, const nlohmann::json& value) override;
443
449 virtual void handleEntityDestroyed(EntityID entityID) override;
450
457 virtual void handlePreSimulationStep() override;
458
465 virtual void copyComponent(EntityID to, EntityID from) override;
466
474 virtual void copyComponent(EntityID to, EntityID from, BaseComponentArray& other) override;
475
480 std::vector<TComponent> mComponentsNext {};
481
486 std::vector<TComponent> mComponentsPrevious {};
487
493 std::unordered_map<EntityID, std::size_t> mEntityToComponentIndex {};
494
500 std::unordered_map<std::size_t, EntityID> mComponentToEntity {};
501 friend class ComponentManager;
502 };
503
504
512 public:
518 explicit ComponentManager(std::weak_ptr<ECSWorld> world): mWorld { world } {};
519 private:
520
527 ComponentManager instantiate(std::weak_ptr<ECSWorld> world) const;
528
534 template<typename TComponent>
536
542 template <typename TComponent>
549 std::string operator()() {
550 return TComponent::getComponentTypeName();
551 }
552 };
553
560 template <typename TComponent>
561 struct getComponentTypeName<std::shared_ptr<TComponent>> {
562 std::string operator()() {
563 return TComponent::getComponentTypeName();
564 }
565 };
566
573 template<typename TComponent>
574 std::shared_ptr<ComponentArray<TComponent>> getComponentArray() const {
575 const std::size_t componentHash { typeid(TComponent).hash_code() };
576 assert(mHashToComponentType.find(componentHash) != mHashToComponentType.end() && "This component type has not been registered");
577 return std::dynamic_pointer_cast<ComponentArray<TComponent>>(mHashToComponentArray.at(componentHash));
578 }
579
586 std::shared_ptr<BaseComponentArray> getComponentArray(const std::string& componentTypeName) const {
587 const std::size_t componentHash { mNameToComponentHash.at(componentTypeName) };
588 return mHashToComponentArray.at(componentHash);
589 }
590
597 template<typename TComponent>
599
606 ComponentType getComponentType(const std::string& typeName) const;
607
624
632 template<typename TComponent>
633 void addComponent(EntityID entityID, const TComponent& component);
634
641 void addComponent(EntityID entityID, const nlohmann::json& jsonComponent);
642
649 template<typename TComponent>
650 void removeComponent(EntityID entityID);
651
658 void removeComponent(EntityID entityID, const std::string& type);
659
670 template<typename TComponent>
671 bool hasComponent(EntityID entityID) const;
672
683 bool hasComponent(EntityID entityID, const std::string& type);
684
693 template<typename TComponent>
694 TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const;
695
705 template<typename TComponent>
706 void updateComponent(EntityID entityID, const TComponent& newValue);
707
716 void updateComponent(EntityID entityID, const nlohmann::json& componentProperties);
717
725 template<typename TComponent>
726 void copyComponent(EntityID to, EntityID from);
727
734 void copyComponents(EntityID to, EntityID from);
735
743 void copyComponents(EntityID to, EntityID from, ComponentManager& other);
744
752 void handleEntityDestroyed(EntityID entityID);
753
760
765 void unregisterAll();
766
772 std::unordered_map<std::string, std::size_t> mNameToComponentHash {};
773
781 std::unordered_map<std::size_t, ComponentType> mHashToComponentType {};
782
787 std::unordered_map<std::size_t, std::shared_ptr<BaseComponentArray>> mHashToComponentArray {};
788
798 std::unordered_map<EntityID, Signature> mEntityToSignature {};
799
804 std::weak_ptr<ECSWorld> mWorld;
805
806 friend class ECSWorld;
807 };
808
814 class BaseSystem : public std::enable_shared_from_this<BaseSystem> {
815 public:
821 BaseSystem(std::weak_ptr<ECSWorld> world): mWorld { world } {}
822
827 virtual ~BaseSystem() = default;
828
835 virtual bool isSingleton() const { return false; }
836
837 protected:
847 template<typename TComponent>
849
855 const std::set<EntityID>& getEnabledEntities();
856
862 const std::set<EntityID>& getEnabledEntities() const;
863
873 template <typename TComponent, typename TSystem>
874 TComponent getComponent_(EntityID entityID, float progress=1.f) const;
875
884 template <typename TComponent, typename TSystem>
885 void updateComponent_(EntityID entityID, const TComponent& component);
886
894 bool isEnabled(EntityID entityID) const;
895
903 bool isRegistered(EntityID entityID) const;
904
911 virtual std::shared_ptr<BaseSystem> instantiate(std::weak_ptr<ECSWorld> world) = 0;
912
917 std::weak_ptr<ECSWorld> mWorld;
918 private:
919
926 void addEntity(EntityID entityID, bool enabled=true);
927
933 void removeEntity(EntityID entityID);
934
940 void enableEntity(EntityID entityID);
946 void disableEntity(EntityID entityID);
947
955 virtual void onEntityEnabled(EntityID entityID) {(void)entityID; /* prevent unused parameter warnings*/}
956
964 virtual void onEntityDisabled(EntityID entityID) { (void)entityID; /* prevent unused parameter warnings*/}
965
972 virtual void onEntityUpdated(EntityID entityID, ComponentType updatedComponentType) {
973 /* prevent unused parameter warnings*/
974 (void)entityID;
975 (void)updatedComponentType;
976 assert(false && "The base class version of onEntityUpdated should never be called");
977 }
978
983 virtual void onInitialize() {}
984
989 virtual void onSimulationActivated() {}
990
996 virtual void onSimulationPreStep(uint32_t simStepMillis) {(void)simStepMillis;/*prevent unused parameter warnings*/}
997
1005 virtual void onSimulationStep(uint32_t simStepMillis) {(void)simStepMillis;/*prevent unused parameter warnings*/}
1006
1012 virtual void onSimulationPostStep(uint32_t simStepMillis) {(void)simStepMillis;/*prevent unused parameter warnings*/}
1013
1019 virtual void onPostTransformUpdate(uint32_t timeStepMillis) {(void)timeStepMillis;/*prevent unused parameter warnings*/}
1020
1030 virtual void onVariableStep(float simulationProgress, uint32_t variableStepMillis) {(void)simulationProgress; (void)variableStepMillis;/*prevent unused parameter warnings*/}
1031
1037 virtual void onPreRenderStep(float simulationProgress) {(void)simulationProgress;/*prevent unused parameter warnings*/}
1038
1044 virtual void onPostRenderStep(float simulationProgress) {(void)simulationProgress;/*prevent unused parameter warnings*/}
1045
1052 virtual void onSimulationDeactivated() {}
1053
1060 virtual void onDestroyed() {}
1061
1066 std::set<EntityID> mEnabledEntities {};
1067
1072 std::set<EntityID> mDisabledEntities {};
1073
1074 friend class SystemManager;
1075 friend class ECSWorld;
1076 };
1077
1086 template <typename TSystemDerived, typename TListenedForComponentsTuple, typename TRequiredComponentsTuple>
1087 class System{ static_assert(false && "Non specialized system cannot be declared"); };
1088
1099 template <typename TSystemDerived, typename ...TListenedForComponents, typename ...TRequiredComponents>
1100 class System<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>: public BaseSystem {
1101
1106 static void registerSelf();
1107
1108 protected:
1109
1117 explicit System(std::weak_ptr<ECSWorld> world): BaseSystem { world } { s_registrator.emptyFunc(); }
1118
1127 template<typename TComponent>
1128 TComponent getComponent(EntityID entityID, float progress=1.f) {
1129 assert(!isSingleton() && "Singletons cannot retrieve components by EntityID alone");
1131 }
1132
1140 template<typename TComponent>
1141 void updateComponent(EntityID entityID, const TComponent& component) {
1142 assert(!isSingleton() && "Singletons cannot retrieve components by EntityID alone");
1144 }
1145
1152 std::shared_ptr<BaseSystem> instantiate(std::weak_ptr<ECSWorld> world) override;
1153 private:
1154
1159 inline static Registrator<System<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>>& s_registrator {
1160 Registrator<System<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>>::getRegistrator()
1161 };
1162
1163 friend class Registrator<System<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>>;
1164 };
1165
1174 public:
1180 explicit SystemManager(std::weak_ptr<ECSWorld> world): mWorld{ world } {}
1181 private:
1188 SystemManager instantiate(std::weak_ptr<ECSWorld> world) const;
1189
1199 template<typename TSystem>
1200 void registerSystem(const Signature& signature, const Signature& listenedForComponents);
1201
1206 void unregisterAll();
1207
1214 template<typename TSystem>
1215 std::shared_ptr<TSystem> getSystem();
1216
1223 template<typename TSystem>
1224 void enableEntity(EntityID entityID);
1225
1235 void enableEntity(EntityID entityID, Signature entitySignature, Signature systemMask = Signature{}.set());
1236
1243 template<typename TSystem>
1244 void disableEntity(EntityID entityID);
1245
1252 void disableEntity(EntityID entityID, Signature entitySignature);
1253
1262 template<typename TSystem>
1263 SystemType getSystemType() const;
1264
1273 template<typename TSystem>
1274 bool isEnabled(EntityID entityID);
1275
1284 template <typename TSystem>
1285 bool isRegistered(EntityID entityID);
1286
1293 void handleEntitySignatureChanged(EntityID entityID, Signature signature);
1294
1300 void handleEntityDestroyed(EntityID entityID);
1301
1309 void handleEntityUpdated(EntityID entityID, Signature signature, ComponentType updatedComponent);
1310
1320 template<typename TSystem>
1321 void handleEntityUpdatedBySystem(EntityID entityID, Signature signature, ComponentType updatedComponent);
1322
1328 void handleInitialize();
1329
1335 void handleSimulationActivated();
1336
1344 void handleSimulationPreStep(uint32_t simStepMillis);
1345
1353 void handleSimulationStep(uint32_t simStepMillis);
1354
1362 void handleSimulationPostStep(uint32_t simStepMillis);
1363
1371 void handlePostTransformUpdate(uint32_t timeStepMillis);
1372
1382 void handleVariableStep(float simulationProgress, uint32_t variableStepMillis);
1383
1391 void handlePreRenderStep(float simulationProgress);
1392
1398 void handlePostRenderStep(float simulationProgress);
1399
1404 void handleSimulationDeactivated();
1405
1412 std::unordered_map<std::string, Signature> mNameToSignature {};
1413
1420 std::unordered_map<std::string, Signature> mNameToListenedForComponents {};
1421
1427 std::unordered_map<std::string, SystemType> mNameToSystemType {};
1428
1433 std::unordered_map<std::string, std::shared_ptr<BaseSystem>> mNameToSystem {};
1434
1439 std::weak_ptr<ECSWorld> mWorld;
1440
1441 friend class ECSWorld;
1442 friend class BaseSystem;
1443 };
1444
1464 class ECSWorld: public std::enable_shared_from_this<ECSWorld> {
1465 public:
1477 static std::weak_ptr<const ECSWorld> getPrototype();
1478
1484 std::shared_ptr<ECSWorld> instantiate() const;
1485
1543 template<typename ...TComponent>
1544 static void registerComponentTypes();
1545
1553 template <typename TSystemDerived, typename TListenedForComponents, typename TRequiredComponents>
1554 struct SystemRegistrationArgs { static_assert(false && "Cannot create unspecialized instance of SystemRegistrationArgs"); };
1555
1566 template <typename TSystemDerived, typename ...TListenedForComponents, typename ...TRequiredComponents>
1567 struct SystemRegistrationArgs<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>> {};
1568
1569
1615 template <typename TSystemDerived, typename ...TListenedForComponents, typename ...TRequiredComponents>
1616 static void registerSystem(SystemRegistrationArgs<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>);
1617
1624 template<typename TSystem>
1625 std::shared_ptr<TSystem> getSystem();
1626
1635 template<typename TSystem>
1636 static std::shared_ptr<TSystem> getSystemPrototype();
1637
1648 template <typename TSingletonSystem>
1649 static std::shared_ptr<TSingletonSystem> getSingletonSystem();
1650
1661 template <typename TSystem>
1663
1670 template<typename TComponent>
1672
1681 template <typename TSystem>
1682 bool isEnabled(EntityID entityID);
1683
1692 template <typename TSystem>
1693 bool isRegistered(EntityID entityID);
1694
1704 template<typename ...TComponents>
1705 Entity createEntity(TComponents...components);
1706
1718 template <typename ...TComponents>
1719 static Entity createEntityPrototype(TComponents...components);
1720
1721 // Simulation lifecycle events
1722
1727 void initialize();
1728
1733 void activateSimulation();
1734
1739 void deactivateSimulation();
1740
1741 // Simulation loop events
1742
1752 void simulationPreStep(uint32_t simStepMillis);
1753
1761 void simulationStep(uint32_t simStepMillis);
1762
1770 void simulationPostStep(uint32_t simStepMillis);
1771
1779 void postTransformUpdate(uint32_t timeStepMillis);
1780
1791 void variableStep(float simulationProgress, uint32_t variableStepMillis);
1792
1800 void preRenderStep(float simulationProgress);
1801
1809 void postRenderStep(float simulationProgress);
1810
1815 void cleanup();
1816
1824 inline WorldID getID() const { return mID; }
1825
1826 private:
1827
1833 static std::shared_ptr<ECSWorld> createWorld();
1834
1840 static std::weak_ptr<ECSWorld> getInstance();
1841
1846 ECSWorld() = default;
1847
1854 void copyComponents(EntityID to, EntityID from);
1855
1863 void copyComponents(EntityID to, EntityID from, ECSWorld& other);
1864
1870 void relocateEntity(Entity& entity);
1871
1879 template<typename ...TComponents>
1880 Entity privateCreateEntity(TComponents...components);
1881
1889 void destroyEntity(EntityID entityID);
1890
1899 template<typename TSystem>
1900 void enableEntity(EntityID entityID);
1901
1910 void enableEntity(EntityID entityID, Signature systemMask = Signature{}.set());
1911
1920 template<typename TSystem>
1921 void disableEntity(EntityID entityID);
1922
1929 void disableEntity(EntityID entityID);
1930
1940 template<typename TComponent>
1941 void addComponent(EntityID entityID, const TComponent& component);
1942
1951 void addComponent(EntityID entityID, const nlohmann::json& jsonComponent);
1952
1953
1964 template<typename TComponent>
1965 TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const;
1966
1977 template<typename TComponent, typename TSystem>
1978 TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const;
1979
1990 template <typename TComponent>
1991 bool hasComponent(EntityID entityID) const;
1992
2004 bool hasComponent(EntityID entityID, const std::string& typeName) const;
2005
2015 template<typename TComponent>
2016 void updateComponent(EntityID entityID, const TComponent& newValue);
2017
2026 void updateComponent(EntityID entityID, const nlohmann::json& newValue);
2027
2038 template<typename TComponent, typename TSystem>
2039 void updateComponent(EntityID entityID, const TComponent& newValue);
2040
2050 template<typename TSystem>
2051 void updateComponent(EntityID entityID, const nlohmann::json& newValue);
2052
2061 template<typename TComponent>
2062 void removeComponent(EntityID entityID);
2063
2070 void removeComponent(EntityID entityID, const std::string& typeName);
2071
2077 void removeComponentsAll(EntityID entityID);
2078
2083 std::unique_ptr<ComponentManager> mComponentManager {nullptr};
2084
2089 std::unique_ptr<SystemManager> mSystemManager {nullptr};
2090
2095 std::vector<EntityID> mDeletedIDs {};
2096
2104
2110
2116
2117 friend class Entity;
2118 friend class BaseSystem;
2119 };
2120
2129 class Entity {
2130 public:
2136 Entity(const Entity& other);
2142 Entity(Entity&& other) noexcept;
2143
2150 Entity& operator=(const Entity& other);
2151
2158 Entity& operator=(Entity&& other) noexcept;
2159
2164 ~Entity();
2165
2171 inline EntityID getID() { return mID; };
2172
2180 void copy(const Entity& other);
2181
2190 template<typename TComponent>
2191 void addComponent(const TComponent& component);
2192
2200 void addComponent(const nlohmann::json& jsonComponent);
2201
2209 template<typename TComponent>
2210 void removeComponent();
2211
2219 void removeComponent(const std::string& typeName);
2220
2221
2231 template<typename TComponent>
2232 bool hasComponent() const;
2233
2243 bool hasComponent(const std::string& typeName) const;
2244
2254 template<typename TComponent>
2255 TComponent getComponent(float simulationProgress=1.f) const;
2256
2265 template<typename TComponent>
2266 void updateComponent(const TComponent& newValue);
2267
2275 void updateComponent(const nlohmann::json& jsonValue);
2276
2286 template<typename TSystem>
2287 bool isEnabled() const;
2288
2298 template <typename TSystem>
2299 bool isRegistered() const;
2300
2308 template<typename TSystem>
2309 void enableSystem();
2310
2318 template<typename TSystem>
2319 void disableSystem();
2320
2326 void disableSystems();
2327
2333 void enableSystems(Signature systemMask);
2334
2340 inline std::weak_ptr<ECSWorld> getWorld() { return mWorld; }
2341
2347 void joinWorld(ECSWorld& world);
2348
2349 private:
2356 Entity(EntityID entityID, std::shared_ptr<ECSWorld> world): mID{ entityID }, mWorld{ world } {};
2357
2363
2368 std::weak_ptr<ECSWorld> mWorld;
2369 friend class ECSWorld;
2370 };
2371
2372
2379 template<typename T>
2380 T Interpolator<T>::operator() (const T& previousState, const T& nextState, float simulationProgress) const {
2381 if(simulationProgress < .5f) return previousState;
2382 return nextState;
2383 }
2384
2385 template<typename TComponent>
2386 void ComponentArray<TComponent>::addComponent(EntityID entityID, const TComponent& component) {
2387 assert(mEntityToComponentIndex.find(entityID) == mEntityToComponentIndex.end() && "Component already added for this entity");
2388
2389 std::size_t newComponentID { mComponentsNext.size() };
2390
2391 const TComponent componentCopy { component };
2392 mComponentsNext.push_back(componentCopy);
2393 mComponentsPrevious.push_back(componentCopy);
2394 mEntityToComponentIndex[entityID] = newComponentID;
2395 mComponentToEntity[newComponentID] = entityID;
2396 }
2397
2398 template <typename TComponent>
2399 void ComponentArray<TComponent>::addComponent(EntityID entityID, const nlohmann::json& jsonComponent) {
2400 addComponent(entityID, ComponentFromJSON<TComponent>::get(jsonComponent));
2401 }
2402
2403 template <typename TComponent>
2404 void ComponentArray<TComponent>::updateComponent(EntityID entityID, const nlohmann::json& jsonComponent) {
2405 updateComponent(entityID, ComponentFromJSON<TComponent>::get(jsonComponent));
2406 }
2407
2408 template<typename TComponent>
2410 return mEntityToComponentIndex.find(entityID) != mEntityToComponentIndex.end();
2411 }
2412
2413 template<typename TComponent>
2415 assert(mEntityToComponentIndex.find(entityID) != mEntityToComponentIndex.end());
2416
2417 const std::size_t removedComponentIndex { mEntityToComponentIndex[entityID] };
2418 const std::size_t lastComponentIndex { mComponentsNext.size() - 1 };
2419 const std::size_t lastComponentEntity { mComponentToEntity[lastComponentIndex] };
2420
2421 // store last component in the removed components place
2422 mComponentsNext[removedComponentIndex] = mComponentsNext[lastComponentIndex];
2423 mComponentsPrevious[removedComponentIndex] = mComponentsPrevious[lastComponentIndex];
2424 // map the last component's entity to its new index
2425 mEntityToComponentIndex[lastComponentEntity] = removedComponentIndex;
2426 // map the removed component's index to the last entity
2427 mComponentToEntity[removedComponentIndex] = lastComponentEntity;
2428
2429 // erase all traces of the removed entity's component and other
2430 // invalid references
2431 mComponentsNext.pop_back();
2432 mComponentsPrevious.pop_back();
2433 mEntityToComponentIndex.erase(entityID);
2434 mComponentToEntity.erase(lastComponentIndex);
2435 }
2436
2437 template <typename TComponent>
2438 TComponent ComponentArray<TComponent>::getComponent(EntityID entityID, float simulationProgress) const {
2439 static Interpolator<TComponent> interpolator{};
2440 assert(mEntityToComponentIndex.find(entityID) != mEntityToComponentIndex.end());
2441 std::size_t componentID { mEntityToComponentIndex.at(entityID) };
2442 return interpolator(mComponentsPrevious[componentID], mComponentsNext[componentID], simulationProgress);
2443 }
2444
2445 template <typename TComponent>
2446 void ComponentArray<TComponent>::updateComponent(EntityID entityID, const TComponent& newComponent) {
2447 assert(mEntityToComponentIndex.find(entityID) != mEntityToComponentIndex.end());
2448 std::size_t componentID { mEntityToComponentIndex.at(entityID) };
2449 mComponentsNext[componentID] = newComponent;
2450 }
2451
2452 template <typename TComponent>
2454 if(mEntityToComponentIndex.find(entityID) != mEntityToComponentIndex.end()) {
2455 removeComponent(entityID);
2456 }
2457 }
2458
2459 template<typename TComponent>
2461 std::copy<typename std::vector<TComponent>::iterator, typename std::vector<TComponent>::iterator>(
2462 mComponentsNext.begin(), mComponentsNext.end(),
2463 mComponentsPrevious.begin()
2464 );
2465 }
2466
2467 template <typename TComponent>
2469 copyComponent(to, from, *this);
2470 }
2471
2472 template <typename TComponent>
2474 assert(to < kMaxEntities && "Cannot copy to an entity with an invalid entity ID");
2475 ComponentArray<TComponent>& downcastOther { static_cast<ComponentArray<TComponent>&>(other) };
2476 if(downcastOther.mEntityToComponentIndex.find(from) == downcastOther.mEntityToComponentIndex.end()) return;
2477
2478 const TComponent componentValueNext { downcastOther.mComponentsNext[downcastOther.mEntityToComponentIndex[from]] };
2479 const TComponent componentValuePrevious { downcastOther.mComponentsPrevious[downcastOther.mEntityToComponentIndex[from]] };
2480
2481 if(mEntityToComponentIndex.find(to) == mEntityToComponentIndex.end()) {
2482 addComponent(to, componentValueNext);
2483 } else {
2484 mComponentsNext[mEntityToComponentIndex[to]] = componentValueNext;
2485 }
2486 mComponentsPrevious[mEntityToComponentIndex[to]] = componentValuePrevious;
2487 }
2488
2489 template<typename TComponent>
2491 const std::size_t componentHash { typeid(TComponent).hash_code() };
2492 // nop when a component array for this type already exists
2493 if(mHashToComponentType.find(componentHash) != mHashToComponentType.end()) {
2494 return;
2495 }
2496
2497 std::string componentTypeName { getComponentTypeName<TComponent>{}() };
2498 assert(mHashToComponentType.size() + 1 < kMaxComponents && "Component type limit reached");
2499 assert(mNameToComponentHash.find(componentTypeName) == mNameToComponentHash.end() && "Another component with this name\
2500 has already been registered");
2501
2502 mNameToComponentHash.insert_or_assign(componentTypeName, componentHash);
2503 mHashToComponentArray.insert_or_assign(
2504 componentHash, std::static_pointer_cast<BaseComponentArray>(std::make_shared<ComponentArray<TComponent>>(mWorld))
2505 );
2506 mHashToComponentType[componentHash] = mHashToComponentType.size();
2507 }
2508
2509 template<typename TComponent>
2511 const std::size_t componentHash { typeid(TComponent).hash_code() };
2512 assert(mHashToComponentType.find(componentHash) != mHashToComponentType.end() && "Component type has not been registered");
2513 return mHashToComponentType.at(componentHash);
2514 }
2515
2516 template<typename TComponent>
2517 void ComponentManager::addComponent(EntityID entityID, const TComponent& component) {
2518 getComponentArray<TComponent>()->addComponent(entityID, component);
2519 mEntityToSignature[entityID].set(getComponentType<TComponent>(), true);
2520 }
2521
2522 template <typename TComponent>
2524 return getComponentArray<TComponent>()->hasComponent(entityID);
2525 }
2526
2527 template<typename TComponent>
2529 getComponentArray<TComponent>()->removeComponent(entityID);
2530 mEntityToSignature[entityID].set(getComponentType<TComponent>(), false);
2531 }
2532
2533 template<typename TComponent>
2534 TComponent ComponentManager::getComponent(EntityID entityID, float simulationProgress) const {
2535 return getComponentArray<TComponent>()->getComponent(entityID, simulationProgress);
2536 }
2537
2538 template<typename TComponent>
2539 void ComponentManager::updateComponent(EntityID entityID, const TComponent& newValue) {
2540 getComponentArray<TComponent>()->updateComponent(entityID, newValue);
2541 }
2542
2543 template <typename TComponent>
2545 assert(mEntityToSignature[from].test(getComponentType<TComponent>()) && "The entity being copied from does not have this component");
2546 getComponentArray<TComponent>()->copyComponent(to, from);
2548 }
2549
2550 template<typename TSystem>
2552 const std::string systemTypeName{ TSystem::getSystemTypeName() };
2553 assert(mNameToSystemType.find(systemTypeName) != mNameToSystemType.end() && "Component type has not been registered");
2554 return mNameToSystemType.at(systemTypeName);
2555 }
2556
2557 template <typename TSystem>
2559 return mSystemManager->isEnabled<TSystem>(entityID);
2560 }
2561 template <typename TSystem>
2563 return mSystemManager->isRegistered<TSystem>(entityID);
2564 }
2565
2566 template <typename TComponent>
2567 bool ECSWorld::hasComponent(EntityID entityID) const {
2568 return mComponentManager->hasComponent<TComponent>(entityID);
2569 }
2570
2571
2572 template <typename TSystemDerived, typename ...TListenedForComponents, typename ...TRequiredComponents>
2573 void System<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>::registerSelf() {
2574 ECSWorld::registerComponentTypes<TRequiredComponents...>();
2575 ECSWorld::registerComponentTypes<TListenedForComponents...>();
2576 ECSWorld::registerSystem(ECSWorld::SystemRegistrationArgs<TSystemDerived, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>{});
2577 }
2578
2579
2580 template<typename TSystem>
2581 void SystemManager::registerSystem(const Signature& signature, const Signature& listenedForComponents) {
2582 const std::string systemTypeName { TSystem::getSystemTypeName() };
2583 assert(mNameToSignature.find(systemTypeName) == mNameToSignature.end() && "System has already been registered");
2584 assert(mNameToSystemType.size() + 1 < kMaxSystems && "System type limit reached");
2585
2586 mNameToSignature[systemTypeName] = signature;
2587 mNameToListenedForComponents[systemTypeName] = listenedForComponents;
2588 mNameToSystem.insert_or_assign(systemTypeName, std::make_shared<TSystem>(mWorld));
2589 mNameToSystemType[systemTypeName] = mNameToSystemType.size();
2590 }
2591
2592 template<typename TSystem>
2593 std::shared_ptr<TSystem> SystemManager::getSystem() {
2594 std::string systemTypeName { TSystem::getSystemTypeName() };
2595 assert(mNameToSignature.find(systemTypeName) != mNameToSignature.end() && "System has not yet been registered");
2596 return std::dynamic_pointer_cast<TSystem>(mNameToSystem[systemTypeName]);
2597 }
2598
2599 template<typename TSystem>
2601 std::string systemTypeName { TSystem::getSystemTypeName() };
2602 mNameToSystem[systemTypeName]->enableEntity(entityID);
2603 }
2604
2605 template<typename TSystem>
2607 std::string systemTypeName { TSystem::getSystemTypeName() };
2608 mNameToSystem[systemTypeName]->disableEntity(entityID);
2609 }
2610
2611 template <typename TComponent>
2612 void Entity::addComponent(const TComponent& component) {
2613 mWorld.lock()->addComponent<TComponent>(mID, component);
2614 }
2615
2616 template <typename TComponent>
2618 return mWorld.lock()->hasComponent<TComponent>(mID);
2619 }
2620
2621 template<typename TComponent>
2622 TComponent Entity::getComponent(float simulationProgress) const {
2623 return mWorld.lock()->getComponent<TComponent>(mID, simulationProgress);
2624 }
2625
2626 template<typename TComponent>
2627 void Entity::updateComponent(const TComponent& newValue) {
2628 mWorld.lock()->updateComponent<TComponent>(mID, newValue);
2629 }
2630
2631 template <typename TComponent>
2633 mWorld.lock()->removeComponent<TComponent>(mID);
2634 }
2635
2636 template <typename TSystem>
2638 mWorld.lock()->enableEntity<TSystem>(mID);
2639 }
2640
2641 template <typename TSystem>
2642 bool Entity::isEnabled() const {
2643 return mWorld.lock()->isEnabled<TSystem>(mID);
2644 }
2645
2646 template <typename TSystem>
2648 return mWorld.lock()->isRegistered<TSystem>(mID);
2649 }
2650
2651 template <typename TSystem>
2653 mWorld.lock()->disableEntity<TSystem>(mID);
2654 }
2655
2656 template <typename TSystem>
2658 const std::string systemTypeName { TSystem::getSystemTypeName() };
2659 return mNameToSystem[systemTypeName]->isEnabled(entityID);
2660 }
2661
2662 template <typename TSystem>
2664 const std::string systemTypeName { TSystem::getSystemTypeName() };
2665 return mNameToSystem[systemTypeName]->isRegistered(entityID);
2666 }
2667
2668 template<typename ...TComponents>
2669 Entity ECSWorld::privateCreateEntity(TComponents...components) {
2670 assert((mNextEntity < kMaxEntities || !mDeletedIDs.empty()) && "Max number of entities reached");
2671
2672 EntityID nextID;
2673 if(!mDeletedIDs.empty()){
2674 nextID = mDeletedIDs.back();
2675 mDeletedIDs.pop_back();
2676 } else {
2677 nextID = mNextEntity++;
2678 }
2679
2680 Entity entity { nextID, shared_from_this()};
2681
2682 (addComponent<TComponents>(nextID, components), ...);
2683 return entity;
2684 }
2685
2686 template<typename TSystem>
2688 return mSystemManager->getSystemType<TSystem>();
2689 }
2690
2691 template<typename TComponent>
2693 return mComponentManager->getComponentType<TComponent>();
2694 }
2695
2696 template<typename TComponent>
2697 void ECSWorld::addComponent(EntityID entityID, const TComponent& component) {
2698 assert(entityID < kMaxEntities && "Cannot add a component to an entity that does not exist");
2699 mComponentManager->addComponent<TComponent>(entityID, component);
2700 Signature signature { mComponentManager->getSignature(entityID) };
2701 mSystemManager->handleEntitySignatureChanged(entityID, signature);
2702 }
2703
2704 template<typename TComponent>
2706 mComponentManager->removeComponent<TComponent>(entityID);
2707 Signature signature { mComponentManager->getSignature(entityID) };
2708 mSystemManager->handleEntitySignatureChanged(entityID, signature);
2709 }
2710
2711 template<typename TSystem>
2713 mSystemManager->enableEntity<TSystem>(entityID);
2714 }
2715
2716 template<typename TSystem>
2718 mSystemManager->disableEntity<TSystem>(entityID);
2719 }
2720
2721 template<typename TComponent>
2722 TComponent ECSWorld::getComponent(EntityID entityID, float progress) const {
2723 return mComponentManager->getComponent<TComponent>(entityID, progress);
2724 }
2725
2726 template<typename TComponent, typename TSystem>
2727 TComponent ECSWorld::getComponent(EntityID entityID, float progress) const {
2728 assert(
2729 (
2730 mSystemManager->mNameToSignature.at(TSystem::getSystemTypeName())
2731 .test(mComponentManager->getComponentType<TComponent>())
2732 )
2733 && "This system cannot access this kind of component"
2734 );
2735 return getComponent<TComponent>(entityID, progress);
2736 }
2737
2738
2739 template<typename TComponent>
2740 void ECSWorld::updateComponent(EntityID entityID, const TComponent& newValue) {
2741 mComponentManager->updateComponent<TComponent>(entityID, newValue);
2742 mSystemManager->handleEntityUpdated(
2743 entityID,
2744 mComponentManager->getSignature(entityID),
2745 mComponentManager->getComponentType<TComponent>()
2746 );
2747 }
2748
2749 template<typename TComponent, typename TSystem>
2750 void ECSWorld::updateComponent(EntityID entityID, const TComponent& newValue) {
2751 assert(
2752 (
2753 mSystemManager->mNameToSignature.at(TSystem::getSystemTypeName())
2754 .test(mComponentManager->getComponentType<TComponent>())
2755 )
2756 && "This system cannot access this kind of component"
2757 );
2758 mComponentManager->updateComponent<TComponent>(entityID, newValue);
2759 mSystemManager->handleEntityUpdatedBySystem<TSystem>(
2760 entityID,
2761 mComponentManager->getSignature(entityID),
2762 mComponentManager->getComponentType<TComponent>()
2763 );
2764 }
2765
2766 template <typename TSystem>
2767 void ECSWorld::updateComponent(EntityID entityID, const nlohmann::json& newValue) {
2768 assert(
2769 (
2770 mSystemManager->mNameToSignature.at(TSystem::getSystemTypeName())
2771 .test(mComponentManager->getComponentType(newValue.at("type")))
2772 )
2773 && "This system cannot access this kind of component"
2774 );
2775 mComponentManager->updateComponent(entityID, newValue);
2776 mSystemManager->handleEntityUpdatedBySystem<TSystem>(
2777 entityID,
2778 mComponentManager->getSignature(entityID),
2779 mComponentManager->getComponentType(newValue.at("type"))
2780 );
2781 }
2782
2783 template<typename ...TComponents>
2785 ((getInstance().lock()->mComponentManager->registerComponentArray<TComponents>()),...);
2786 }
2787
2788 template<typename TSystem, typename ...TListenedForComponents, typename ...TRequiredComponents>
2790 ECSWorld::SystemRegistrationArgs<TSystem, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>
2791 ) {
2792 Signature listensFor {};
2793 Signature required {};
2794
2795 (listensFor.set(getInstance().lock()->mComponentManager->getComponentType<TListenedForComponents>()), ...);
2796 (required.set(getInstance().lock()->mComponentManager->getComponentType<TRequiredComponents>()), ...);
2797
2798 getInstance().lock()->mSystemManager->registerSystem<TSystem>(required|listensFor, listensFor);
2799 }
2800
2801 template<typename ...TComponents>
2802 Entity ECSWorld::createEntity(TComponents...components) {
2803 return privateCreateEntity<TComponents...>(components...);
2804 }
2805
2806 template <typename ...TComponents>
2807 Entity ECSWorld::createEntityPrototype(TComponents...components) {
2808 return ECSWorld::getInstance().lock()->privateCreateEntity<TComponents...>(components...);
2809 }
2810
2811 template<typename TSystem>
2812 std::shared_ptr<TSystem> ECSWorld::getSystem() {
2813 return mSystemManager->getSystem<TSystem>();
2814 }
2815
2816 template<typename TSystem>
2817 std::shared_ptr<TSystem> ECSWorld::getSystemPrototype() {
2818 return getInstance().lock()->mSystemManager->getSystem<TSystem>();
2819 }
2820
2821 template <typename TSingletonSystem>
2822 std::shared_ptr<TSingletonSystem> ECSWorld::getSingletonSystem() {
2823 std::shared_ptr<TSingletonSystem> system { getInstance().lock()->getSystem<TSingletonSystem>() };
2824 assert(system->isSingleton() && "System specified is not an ECSWorld-aware singleton system");
2825 return system;
2826 }
2827
2828 template<typename TComponent>
2830 return mWorld.lock()->getComponentType<TComponent>();
2831 }
2832
2833 template<typename TComponent, typename TSystem>
2834 TComponent BaseSystem::getComponent_(EntityID entityID, float progress) const {
2835 assert(!isSingleton() && "Singletons cannot retrieve entity components through entity ID alone");
2836 return mWorld.lock()->getComponent<TComponent, TSystem>(entityID, progress);
2837 }
2838 template<typename TSystem, typename ...TListenedForComponents, typename ...TRequiredComponents>
2839 std::shared_ptr<BaseSystem> System<TSystem, std::tuple<TListenedForComponents...>, std::tuple<TRequiredComponents...>>::instantiate(std::weak_ptr<ECSWorld> world) {
2840 if(isSingleton()) return shared_from_this();
2841 return std::make_shared<TSystem>(world);
2842 }
2843
2844 template <typename TComponent>
2845 std::shared_ptr<BaseComponentArray> ComponentArray<TComponent>::instantiate(std::weak_ptr<ECSWorld> world) const {
2846 return std::make_shared<ComponentArray<TComponent>>(world);
2847 }
2848
2849 template<typename TComponent, typename TSystem>
2850 void BaseSystem::updateComponent_(EntityID entityID, const TComponent& component) {
2851 assert(!isSingleton() && "Singletons cannot retrieve entity components through entity ID alone");
2852 mWorld.lock()->updateComponent<TComponent, TSystem>(entityID, component);
2853 }
2854
2855 template<typename TSystem>
2857 std::string originatingSystemTypeName { TSystem::getSystemTypeName() };
2858 for(const auto& pair: mNameToSignature) {
2859 // see if the updated entity's signature matches that of the system
2860 if((pair.second&signature) != pair.second) continue;
2861
2862 // suppress update callback from the system that caused this update
2863 if(pair.first == originatingSystemTypeName) continue;
2864
2865 // see if the system is listening for updates to this system
2866 if(!mNameToListenedForComponents[pair.first].test(updatedComponent)) continue;
2867
2868 // ignore disabled and singleton systems
2869 BaseSystem& system { *(mNameToSystem[pair.first]).get() };
2870 if(system.isSingleton() || !system.isEnabled(entityID)) continue;
2871
2872 // apply update
2873 system.onEntityUpdated(entityID, updatedComponent);
2874 }
2875 }
2876
2877}
2878
2879#endif
An abstract base class for all ECS component arrays.
Definition ecs_world.hpp:168
virtual void copyComponent(EntityID to, EntityID from, BaseComponentArray &other)=0
Handles the copying of a component from one entity to another, where the other entity belongs to anot...
virtual void updateComponent(EntityID to, const nlohmann::json &jsonComponent)=0
Updates the component associated with an entity based on a json description of a new component.
virtual ~BaseComponentArray()=default
Destroy the Base Component Array object.
virtual std::shared_ptr< BaseComponentArray > instantiate(std::weak_ptr< ECSWorld > world) const =0
Creates a fresh, empty component array and associates it with a new World.
std::weak_ptr< ECSWorld > mWorld
A reference to the world to which this component array belongs.
Definition ecs_world.hpp:262
virtual void handleEntityDestroyed(EntityID entityID)=0
A virtual function that handles the side-effect of destroying an entity, i.e., deleting its component...
virtual void copyComponent(EntityID to, EntityID from)=0
Handles the copying of a component from one entity to another within the same array.
virtual void addComponent(EntityID to, const nlohmann::json &jsonComponent)=0
Constructs and adds a component to an array based on its json description.
BaseComponentArray(std::weak_ptr< ECSWorld > world)
Construct a new Base Component Array object.
Definition ecs_world.hpp:176
virtual bool hasComponent(EntityID entityID) const =0
Tests whether this array has an entry for this entity.
virtual void removeComponent(EntityID entityID)=0
Removes the component associated with this entity, if present.
virtual void handlePreSimulationStep()=0
An unimplemented callback for a step that occurs before each simulation step.
The base class that acts as the interface between the engine's ECS system and a particular built-in o...
Definition ecs_world.hpp:814
virtual void onInitialize()
An overridable callback for right after an ECS world has just been created.
Definition ecs_world.hpp:983
virtual void onSimulationDeactivated()
Overridable callback called just after the ECS world owning this system has been deactivated.
Definition ecs_world.hpp:1052
virtual void onPreRenderStep(float simulationProgress)
Overridable callback called just before the render step takes place.
Definition ecs_world.hpp:1037
virtual void onSimulationPostStep(uint32_t simStepMillis)
An overridable callback called once at the end of this simulation step, and after related transform u...
Definition ecs_world.hpp:1012
virtual void onEntityUpdated(EntityID entityID, ComponentType updatedComponentType)
An overridable callback for when another system has updated a component shared by this system and an ...
Definition ecs_world.hpp:972
void updateComponent_(EntityID entityID, const TComponent &component)
The actual implementation of updateComponent for a system.
Definition ecs_world.hpp:2850
virtual ~BaseSystem()=default
Destroy the Base System object.
void removeEntity(EntityID entityID)
Removes an entity from this system.
Definition ecs_world.cpp:128
virtual void onVariableStep(float simulationProgress, uint32_t variableStepMillis)
Overridable callback called after all simulation updates (if any) for the current frame have been com...
Definition ecs_world.hpp:1030
void enableEntity(EntityID entityID)
Allows a registered entity to be influenced by this system.
Definition ecs_world.cpp:81
std::weak_ptr< ECSWorld > mWorld
A reference to the world this system belongs to.
Definition ecs_world.hpp:917
virtual void onEntityDisabled(EntityID entityID)
An overridable callback for when an entity has been disabled.
Definition ecs_world.hpp:964
void disableEntity(EntityID entityID)
Prevents the influencing of an entity by this system.
Definition ecs_world.cpp:100
BaseSystem(std::weak_ptr< ECSWorld > world)
Construct a new Base System object.
Definition ecs_world.hpp:821
virtual void onPostTransformUpdate(uint32_t timeStepMillis)
An overridable callback called after all the transforms in the scene are updated by the scene system.
Definition ecs_world.hpp:1019
virtual std::shared_ptr< BaseSystem > instantiate(std::weak_ptr< ECSWorld > world)=0
Creates a fresh copy of this system and associates it with a new ECS World, using this system as its ...
bool isEnabled(EntityID entityID) const
Tests whether a particular entity is active for this system.
Definition ecs_world.cpp:141
virtual void onEntityEnabled(EntityID entityID)
An overridable callback for when an entity has been enabled.
Definition ecs_world.hpp:955
std::set< EntityID > mEnabledEntities
A set of all entities that are actively influenced by this system, managed by this system's ECS world...
Definition ecs_world.hpp:1066
virtual void onDestroyed()
Overridable callback called just before this system is destroyed.
Definition ecs_world.hpp:1060
virtual void onSimulationActivated()
An overridable callback for right after the ECS World has been activated.
Definition ecs_world.hpp:989
virtual void onSimulationStep(uint32_t simStepMillis)
An overridable callback called once in the middle of every simulation step.
Definition ecs_world.hpp:1005
const std::set< EntityID > & getEnabledEntities()
Get a set of all entities that are influenced by this System.
Definition ecs_world.cpp:133
virtual void onPostRenderStep(float simulationProgress)
Overridable callback called just after the render step takes place.
Definition ecs_world.hpp:1044
ComponentType getComponentType() const
Get the component type ID for a given component type.
Definition ecs_world.hpp:2829
virtual bool isSingleton() const
A method to query whether a particular System is a singleton, or is instantiated for each world in th...
Definition ecs_world.hpp:835
void addEntity(EntityID entityID, bool enabled=true)
Adds an entity to this system.
Definition ecs_world.cpp:112
std::set< EntityID > mDisabledEntities
A set of all entities that are compatible with this system, but have not been enabled for it.
Definition ecs_world.hpp:1072
virtual void onSimulationPreStep(uint32_t simStepMillis)
An overridable callback called once at the beginning of every simulation step in the game loop.
Definition ecs_world.hpp:996
TComponent getComponent_(EntityID entityID, float progress=1.f) const
The actual implementation of getComponent for a system.
Definition ecs_world.hpp:2834
bool isRegistered(EntityID entityID) const
Tests whether a particular entity can be influenced by this system.
Definition ecs_world.cpp:145
A class that implements BaseComponentArray specializing it for a component of type TComponent.
Definition ecs_world.hpp:366
std::shared_ptr< BaseComponentArray > instantiate(std::weak_ptr< ECSWorld > world) const override
Creates a new component array of the same type as this and associated with a new World.
Definition ecs_world.hpp:2845
std::unordered_map< std::size_t, EntityID > mComponentToEntity
A mapping from the index of a component to the ID of the entity that owns that component.
Definition ecs_world.hpp:500
void removeComponent(EntityID entityID) override
Removes the component associated with a specific entity, maintaining packing but not order.
Definition ecs_world.hpp:2414
virtual void handlePreSimulationStep() override
A callback for the start of a simulation step.
Definition ecs_world.hpp:2460
void addComponent(EntityID entityID, const TComponent &component)
Adds a component belonging to this entity to this array.
Definition ecs_world.hpp:2386
ComponentArray(std::weak_ptr< ECSWorld > world)
Construct a new Component Array object.
Definition ecs_world.hpp:373
void updateComponent(EntityID entityID, const TComponent &newValue)
Updates the value of the component belonging to this entity.
Definition ecs_world.hpp:2446
std::vector< TComponent > mComponentsPrevious
An array containing the state of each entity's component as seen in the last simulation tick.
Definition ecs_world.hpp:486
bool hasComponent(EntityID entityID) const override
Tests whether an entry for a component belonging to this entity is present.
Definition ecs_world.hpp:2409
TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const
Get the component object.
Definition ecs_world.hpp:2438
std::unordered_map< EntityID, std::size_t > mEntityToComponentIndex
A mapping from the ID of an entity to the index in the component array that stores the entity's compo...
Definition ecs_world.hpp:493
virtual void handleEntityDestroyed(EntityID entityID) override
A callback to handle the side effect of the destruction of an entity. Here: deletion of the component...
Definition ecs_world.hpp:2453
virtual void copyComponent(EntityID to, EntityID from) override
Handles the copying of a component belonging to one entity to another.
Definition ecs_world.hpp:2468
std::vector< TComponent > mComponentsNext
An array containing the state of each entity's component as will be seen at the start of the next sim...
Definition ecs_world.hpp:480
An object that stores and manages updates to all the component arrays instantiated for this ECS World...
Definition ecs_world.hpp:511
void unregisterAll()
Unregisters all component arrays associated with this manager, as part of the destruction process for...
Definition ecs_world.cpp:435
Signature getSignature(EntityID entityID)
Get the component signature for a given entity.
Definition ecs_world.cpp:390
void copyComponent(EntityID to, EntityID from)
Copies a component value from one component to another within the same component array.
Definition ecs_world.hpp:2544
void handlePreSimulationStep()
Callback for the start of a simulation step, where the contents of every component's next member is c...
Definition ecs_world.cpp:520
std::unordered_map< EntityID, Signature > mEntityToSignature
Stores the component signature of each entity.
Definition ecs_world.hpp:798
void addComponent(EntityID entityID, const TComponent &component)
Adds a component entry for this entity in the array specified.
Definition ecs_world.hpp:2517
TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const
Get the component value for this entity.
Definition ecs_world.hpp:2534
void updateComponent(EntityID entityID, const TComponent &newValue)
Updates a component belonging to an entity with its new value.
Definition ecs_world.hpp:2539
std::shared_ptr< BaseComponentArray > getComponentArray(const std::string &componentTypeName) const
Get the Component Array object.
Definition ecs_world.hpp:586
std::unordered_map< std::size_t, ComponentType > mHashToComponentType
Maps a component's type hash to its ComponentType.
Definition ecs_world.hpp:781
void copyComponents(EntityID to, EntityID from)
Copies all components from one entity and updates or adds them to the other.
Definition ecs_world.cpp:399
bool hasComponent(EntityID entityID) const
Tests whether an entity has a component of a particular type.
Definition ecs_world.hpp:2523
std::unordered_map< std::size_t, std::shared_ptr< BaseComponentArray > > mHashToComponentArray
Maps the hash of a component type to its corresponding ComponentArray.
Definition ecs_world.hpp:787
std::unordered_map< std::string, std::size_t > mNameToComponentHash
Maps each component type name to its corresponding hash.
Definition ecs_world.hpp:772
std::shared_ptr< ComponentArray< TComponent > > getComponentArray() const
Get the (specialized) Component Array object.
Definition ecs_world.hpp:574
void removeComponent(EntityID entityID)
Removes the component of the type specified from the entity.
Definition ecs_world.hpp:2528
ComponentManager(std::weak_ptr< ECSWorld > world)
Construct a new Component Manager object.
Definition ecs_world.hpp:518
std::weak_ptr< ECSWorld > mWorld
Holds a reference to the ECS world this component manager manages component arrays for.
Definition ecs_world.hpp:804
void handleEntityDestroyed(EntityID entityID)
Handles component arrays specific side effect of entity destruction.
Definition ecs_world.cpp:411
void registerComponentArray()
A method to allow a new component type to register itself with the ECS system for this project.
Definition ecs_world.hpp:2490
ComponentManager instantiate(std::weak_ptr< ECSWorld > world) const
Constructs a new component manager and associates it with the world passed in as argument....
Definition ecs_world.cpp:355
ComponentType getComponentType() const
Get the component type ID for a given component type.
Definition ecs_world.hpp:2510
A class that represents a set of systems, entities, and components, that are all interrelated,...
Definition ecs_world.hpp:1464
SystemType getSystemType()
Get the SystemType id for a particular system.
Definition ecs_world.hpp:2687
void cleanup()
Loses references to member systems, component arrays, and entities, resulting in their destruction.
Definition ecs_world.cpp:581
bool isRegistered(EntityID entityID)
Tests whether an entity is eligible for membership with a system, per its component signature.
Definition ecs_world.hpp:2562
void initialize()
Runs the initialization step for this world and the systems that belong to it.
Definition ecs_world.cpp:538
bool isEnabled(EntityID entityID)
Tests whether a particular entity is enabled for a particular system.
Definition ecs_world.hpp:2558
static Entity createEntityPrototype(TComponents...components)
Create a prototype entity object.
Definition ecs_world.hpp:2807
std::shared_ptr< ECSWorld > instantiate() const
Creates a new ECSWorld using the systems and component arrays present in this one as a template.
Definition ecs_world.cpp:491
void simulationPreStep(uint32_t simStepMillis)
Runs callbacks associated with the start of a simulation update.
Definition ecs_world.cpp:557
bool hasComponent(EntityID entityID) const
Tests whether an entity has a component of a specific type.
Definition ecs_world.hpp:2567
static void registerComponentTypes()
Registers ComponentArrays for each type of component present in the component type list,...
Definition ecs_world.hpp:2784
void enableEntity(EntityID entityID)
Enables an entity for a specific system.
Definition ecs_world.hpp:2712
EntityID mNextEntity
A new EntityID that has never been created before in this world.
Definition ecs_world.hpp:2103
ECSWorld()=default
Construct a new ECSWorld object.
TComponent getComponent(EntityID entityID, float simulationProgress=1.f) const
Get a component associated with an entity.
Definition ecs_world.hpp:2722
static std::weak_ptr< const ECSWorld > getPrototype()
Get the prototype ECSWorld.
Definition ecs_world.cpp:475
static std::shared_ptr< TSingletonSystem > getSingletonSystem()
Get a system that has been marked as a singleton System.
Definition ecs_world.hpp:2822
void simulationPostStep(uint32_t simStepMillis)
Runs calbacks associated with the end of the simulation step.
Definition ecs_world.cpp:564
void simulationStep(uint32_t simStepMillis)
Runs callbacks associated with the simulation step.
Definition ecs_world.cpp:561
WorldID getID() const
Gets the ID associated with this world.
Definition ecs_world.hpp:1824
void destroyEntity(EntityID entityID)
Destroys an Entity with a specific ID.
Definition ecs_world.cpp:513
std::vector< EntityID > mDeletedIDs
A list of previously existing entity IDs that were since retired and are available to be used again.
Definition ecs_world.hpp:2095
void relocateEntity(Entity &entity)
Moves an entity from one ECSWorld to this one.
Definition ecs_world.cpp:62
void copyComponents(EntityID to, EntityID from)
Copies components from one entity to another within a single ECSWorld.
Definition ecs_world.cpp:527
ComponentType getComponentType() const
Get the component type ID for a given component type.
Definition ecs_world.hpp:2692
void preRenderStep(float simulationProgress)
Runs callbacks associated with the start of the rendering step.
Definition ecs_world.cpp:574
std::unique_ptr< SystemManager > mSystemManager
A reference to this world SystemManager.
Definition ecs_world.hpp:2089
void activateSimulation()
Marks this world as an active one, calling the activation callbacks of systems that belong to it.
Definition ecs_world.cpp:541
void removeComponent(EntityID entityID)
Removes a component from an entity.
Definition ecs_world.hpp:2705
Entity privateCreateEntity(TComponents...components)
Creates a new entity and assigns it the components specified as arguments.
Definition ecs_world.hpp:2669
WorldID mID
The unique ID associated with this ECSWorld.
Definition ecs_world.hpp:2109
std::unique_ptr< ComponentManager > mComponentManager
A reference to this world's ComponentManager.
Definition ecs_world.hpp:2083
static std::shared_ptr< TSystem > getSystemPrototype()
Get the system object of a specific type belonging to the prototype ECSWorld.
Definition ecs_world.hpp:2817
void updateComponent(EntityID entityID, const TComponent &newValue)
Updates a component belonging to an entity with a new value.
Definition ecs_world.hpp:2740
Entity createEntity(TComponents...components)
Creates a new entity that will exist in this ECSWorld.
Definition ecs_world.hpp:2802
void postRenderStep(float simulationProgress)
Runs callbacks associated with the end of the rendering step.
Definition ecs_world.cpp:577
void postTransformUpdate(uint32_t timeStepMillis)
Runs callbacks associated with the end of transform updates.
Definition ecs_world.cpp:568
std::shared_ptr< TSystem > getSystem()
Get the system object of a specific type belonging to this ECSWorld.
Definition ecs_world.hpp:2812
void disableEntity(EntityID entityID)
Disables an entity on a particular system.
Definition ecs_world.hpp:2717
void variableStep(float simulationProgress, uint32_t variableStepMillis)
Runs callbacks associated with the variable step of the game loop.
Definition ecs_world.cpp:571
void deactivateSimulation()
Marks ths world as an inactive one, and suspends operation for its member systems.
Definition ecs_world.cpp:544
static void registerSystem(SystemRegistrationArgs< TSystemDerived, std::tuple< TListenedForComponents... >, std::tuple< TRequiredComponents... > >)
Registers a System with the ECS System for this project.
static WorldID s_nextWorld
The ID the next ECSWorld to be instantiated will receive.
Definition ecs_world.hpp:2115
static std::weak_ptr< ECSWorld > getInstance()
Creates an instance of the prototype ECSWorld, and returns a reference to it.
Definition ecs_world.cpp:486
void addComponent(EntityID entityID, const TComponent &component)
Adds a new component to the entity.
Definition ecs_world.hpp:2697
The Entity is a wrapper on an entity ID, used as the primary interface between an application and the...
Definition ecs_world.hpp:2129
void addComponent(const TComponent &component)
Adds a new component to this Entity.
Definition ecs_world.hpp:2612
EntityID getID()
Gets the ID associated with this Entity.
Definition ecs_world.hpp:2171
std::weak_ptr< ECSWorld > mWorld
The world this Entity belongs to.
Definition ecs_world.hpp:2368
void updateComponent(const TComponent &newValue)
Updates the value of a component belonging to this Entity.
Definition ecs_world.hpp:2627
void disableSystem()
Disables this entity for a particular system.
Definition ecs_world.hpp:2652
EntityID mID
The ID of this entity within its owning ECSWorld.
Definition ecs_world.hpp:2362
Entity & operator=(const Entity &other)
Copies an Entity object, replacing any component values currently present on this one.
Definition ecs_world.cpp:32
bool hasComponent() const
Tests whether this entity has a particular component.
Definition ecs_world.hpp:2617
std::weak_ptr< ECSWorld > getWorld()
Get the ECSWorld object this Entity belongs to.
Definition ecs_world.hpp:2340
void enableSystem()
Enables this Entity for a particular System.
Definition ecs_world.hpp:2637
Entity(const Entity &other)
Construct a new Entity object.
Definition ecs_world.cpp:16
bool isRegistered() const
Tests whether this entity is eligible for participation with a given system.
Definition ecs_world.hpp:2647
Entity(EntityID entityID, std::shared_ptr< ECSWorld > world)
Construct a new Entity object, with a new ID as a member of a new ECSWorld.
Definition ecs_world.hpp:2356
bool isEnabled() const
Tests whether this entity is enabled for a particular system.
Definition ecs_world.hpp:2642
TComponent getComponent(float simulationProgress=1.f) const
Get the value of the component at a specific time this frame.
Definition ecs_world.hpp:2622
void removeComponent()
Removes a component from an entity.
Definition ecs_world.hpp:2632
A template class for interpolating components between simulation frames for various purposes.
Definition ecs_world.hpp:337
RangeMapperLinear mProgressLimits
a functor that performs the actual interpolation in the default case
Definition ecs_world.hpp:354
A simple linear interpolation implementation between a fixed input and output range.
Definition util.hpp:213
Helper class for registering a class at program startup.
Definition registrator.hpp:64
Holds references to all the systems belonging to this manager's ECSWorld.
Definition ecs_world.hpp:1173
void disableEntity(EntityID entityID)
Disables an entity for a particular system.
Definition ecs_world.hpp:2606
std::unordered_map< std::string, Signature > mNameToListenedForComponents
Mapping from the system type name for a system to its component listening signature.
Definition ecs_world.hpp:1420
std::weak_ptr< ECSWorld > mWorld
The world this System manager belongs to.
Definition ecs_world.hpp:1439
bool isEnabled(EntityID entityID)
Tests whether an entity is enabled for a particular system.
Definition ecs_world.hpp:2657
SystemManager(std::weak_ptr< ECSWorld > world)
Construct a new System Manager object.
Definition ecs_world.hpp:1180
SystemType getSystemType() const
Get the SystemType for a system.
Definition ecs_world.hpp:2551
std::unordered_map< std::string, std::shared_ptr< BaseSystem > > mNameToSystem
Maps system type names to references to the actual in-memory Systems they represent.
Definition ecs_world.hpp:1433
std::shared_ptr< TSystem > getSystem()
Gets an instance of a system belonging to this ECS World.
Definition ecs_world.hpp:2593
void enableEntity(EntityID entityID)
Enables the visibility of an entity to a particular system.
Definition ecs_world.hpp:2600
std::unordered_map< std::string, Signature > mNameToSignature
Mapping from the system type name for a system to its component signature.
Definition ecs_world.hpp:1412
std::unordered_map< std::string, SystemType > mNameToSystemType
Maps system type names to their corresponding SystemType values.
Definition ecs_world.hpp:1427
void handleEntityUpdatedBySystem(EntityID entityID, Signature signature, ComponentType updatedComponent)
Handles an update to an entity by running a callback on all interested systems (except the one that t...
Definition ecs_world.hpp:2856
void registerSystem(const Signature &signature, const Signature &listenedForComponents)
During static initialization, adds the new System type and its component signatures to its tables.
Definition ecs_world.hpp:2581
bool isRegistered(EntityID entityID)
Tests whether an entity is eligible for participation in a particular system.
Definition ecs_world.hpp:2663
void updateComponent(EntityID entityID, const TComponent &component)
Updates a component via this system's specialized version of updateComponent.
Definition ecs_world.hpp:1141
std::shared_ptr< BaseSystem > instantiate(std::weak_ptr< ECSWorld > world) override
Instantiates a fresh System using this one as a template, and associates it with a new world.
System(std::weak_ptr< ECSWorld > world)
Construct a new System object.
Definition ecs_world.hpp:1117
static void registerSelf()
Helper function called during static initialization to make this project's ECS system aware that this...
Definition ecs_world.hpp:2573
TComponent getComponent(EntityID entityID, float progress=1.f)
Gets the component belonging to the entity using this System's specialized version of getComponent.
Definition ecs_world.hpp:1128
static Registrator< System< TSystemDerived, std::tuple< TListenedForComponents... >, std::tuple< TRequiredComponents... > > > & s_registrator
A specialization of Registrator<T> which ensures registerSelf() is called during this project's stati...
Definition ecs_world.hpp:1159
A system template that disables systems with this form of declaration.
Definition ecs_world.hpp:1087
ECSType ComponentType
An unsigned integer representing the type of a component.
Definition ecs_world.hpp:103
T operator()(const T &previousState, const T &nextState, float simulationProgress=1.f) const
Returns an interpolated value for a component between two given states.
Definition ecs_world.hpp:2380
constexpr ComponentType kMaxComponents
A constant that restricts the number of definable components in a project.
Definition ecs_world.hpp:132
std::bitset< kMaxComponents > Signature
A 255 bit number, where each enabled bit represents a relationship between an entity and some ECS rel...
Definition ecs_world.hpp:154
constexpr SystemType kMaxSystems
A constant that restricts the number of definable systems in a project.
Definition ecs_world.hpp:139
ECSType SystemType
An unsigned integer representing the type of a system.
Definition ecs_world.hpp:112
std::uint8_t ECSType
A number tag used to represent components and systems.
Definition ecs_world.hpp:93
constexpr EntityID kMaxEntities
A user-set constant which limits the number of creatable entities in a single ECS system.
Definition ecs_world.hpp:119
std::pair< WorldID, EntityID > UniversalEntityID
An ID that uniquely identifies an entity.
Definition ecs_world.hpp:85
std::uint64_t EntityID
A single unsigned integer used as a name for an entity managed by an ECS system.
Definition ecs_world.hpp:68
std::uint64_t WorldID
An unsigned integer representing the name of an ECS world.
Definition ecs_world.hpp:76
constexpr ECSType kMaxECSTypes
A constant used to restrict the number of definable system and component types in a project.
Definition ecs_world.hpp:125
Namespace containing all class definitions and functions related to the ToyMaker engine.
Definition application.hpp:25
STL namespace.
Contains the definition for the Registrator<T> utility class, used anywhere that automatic registrati...
A struct that describes how a JSON component description is turned into a component.
Definition ecs_world.hpp:289
static TComponent get(const nlohmann::json &jsonComponent)
Get method that automatically invokes a from_json function, found by nlohmann json.
Definition ecs_world.hpp:296
Helper function for retrieving the component type string defined as part of the component.
Definition ecs_world.hpp:543
std::string operator()()
The method that retrieves the component type string.
Definition ecs_world.hpp:549
Prevents the use of the unspecialized version of SystemRegistrationArgs.
Definition ecs_world.hpp:1554
Contains a couple of classes not tied to any part of the engine in particular, but useful to those pa...