From 5e3a2492c7bb73daa4e27398daaf490d09980ff3 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Wed, 22 Jun 2022 17:41:59 -0400 Subject: Base system viewer with data loaded from csv files --- include/ecs.hpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 include/ecs.hpp (limited to 'include/ecs.hpp') diff --git a/include/ecs.hpp b/include/ecs.hpp new file mode 100644 index 0000000..ab5e2b2 --- /dev/null +++ b/include/ecs.hpp @@ -0,0 +1,139 @@ +#ifndef ECS_HPP +#define ECS_HPP 1 + +#include "entitycomponents.hpp" +#include "util.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace ecs { + +struct ComponentContainer { + std::vector packed{}; + std::vector sparse{}; + std::queue free{}; + + void resize(size_t n) { sparse.resize(n, -1); } + + template + void insert(unsigned id, const T &c) { + assert(sparse.size() > id); + if(free.empty()) { + sparse[id] = (int)packed.size(); + packed.push_back(c); + }else { + sparse[id] = (int)free.front(); + packed[sparse[id]] = c; + free.pop(); + } + } + + void remove(unsigned id) { + assert(sparse.size() > id); + if(sparse[id] > -1) { + free.push((unsigned)sparse[id]); + } + sparse[id] = -1; + } + + template + T &reduce(unsigned id) { + assert(sparse.size() > id); + assert(sparse[id] > -1); + return std::get(packed[sparse[id]]); + } +}; + +class EntityMan; +struct Entity { + EntityMan *man; + component_sig sig{}; + unsigned id; + + Entity(const Entity &e) = default; + Entity(EntityMan *Man, unsigned Id) : + man(Man), sig(0), id(Id) {} + + + template + constexpr bool contains() { return sig.test(get_index()); } + + template + T &get(); + + template + Entity &addComponent(const T &component); +}; + +class EntityMan { + std::array> m_components; + std::vector m_entities; + std::queue m_free; +public: + Entity &operator[](std::size_t i) { return m_entities[i]; } + + Entity newEntity() { + std::size_t newid = 0; + if(!m_free.empty()) { + newid = m_free.front(); + m_free.pop(); + }else{ + newid = m_entities.size(); + m_entities.emplace_back(this, newid); + for(auto &container : m_components) container.resize(m_entities.size()); + } + return m_entities[newid]; + } + + void deleteEntity(Entity &e) { + for(auto &container : m_components) container.remove(e.id); + e.sig.reset(); + m_free.push(e.id); + } + + template + T &get(const Entity &e) { + constexpr unsigned cid = get_index(); + return m_components[cid].reduce(e.id); + } + + template + auto getWith() { + constexpr unsigned cid = get_index(); + auto e_hc = [](Entity const e) { return e.sig[cid]; }; + return std::ranges::views::filter(m_entities, e_hc); + } + + std::span all() { + return std::span(m_entities.begin(), m_entities.end()); + } + + std::size_t size() { return m_entities.size(); } + + template + Entity &addComponent(Entity &entity, const T& component) { + constexpr unsigned cid = get_index(); + m_components[cid].insert(entity.id, component); + m_entities[entity.id].sig[cid] = 1; + return entity; + } +}; + +template +T &Entity::get() { + return man->get(*this); +} + +template +Entity &Entity::addComponent(const T& component) { + return man->addComponent(*this, component); +} + +} + +#endif -- cgit v1.2.1