Skip to content

Commit

Permalink
Merge pull request #110 from AGH-Code-Industry/chris_ecs
Browse files Browse the repository at this point in the history
De-templated parts of ECS
  • Loading branch information
Chris-plusplus authored Oct 24, 2024
2 parents b9d8db2 + dcf698e commit 45fe52a
Show file tree
Hide file tree
Showing 30 changed files with 732 additions and 1,029 deletions.
3 changes: 1 addition & 2 deletions include/Ecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
#include "ecs/ComponentPoolIterator.h"
#include "ecs/ComponentSpecs.h"
#include "ecs/ComponentTraits.h"
#include "ecs/View.h"
// manual break
#include "ecs/Domain.h"
#include "ecs/Entity.h"
#include "ecs/EntityPool.h"
#include "ecs/EntitySpecs.h"
#include "ecs/EntityTraits.h"
#include "ecs/InClassComponentSpecs.h"
#include "ecs/SparseSet.h"
#include "ecs/View.h"
32 changes: 11 additions & 21 deletions include/ecs/CommonComponentPool.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#pragma once

#include <ranges>

#include "SparseSet.h"
#include <utils/ReadonlyCounter.h>

namespace arch::ecs {

template<class E, bool Const, class I, class Ex>
template<bool Const, class I, class Ex>
class View;

}
Expand All @@ -14,36 +16,24 @@ namespace arch::ecs::_details { // NOLINT

/// @brief Abstract class with behavior shared between all ComponentPools
/// @tparam E - entity type
template<class E>
class CommonComponentPool: public _details::SparseSet<E>, public utils::ReadonlyCounter<size_t> {
class CommonComponentPool: public _details::SparseSet, public utils::ReadonlyCounter<size_t> {
public:
/// @brief Removes component from given entity
/// @param entity - entity to remove component from
/// @return If component was actually removed
virtual bool removeComponent(const E entity) noexcept = 0;

using _details::SparseSet<E>::contains;

using utils::ReadonlyCounter<size_t>::count;
virtual bool removeComponent(const Entity entity) noexcept = 0;

protected:
template<class, bool, class, class>
template<bool, class, class>
friend class ::arch::ecs::View;

using _details::SparseSet<E>::_sparseAssure;
using _details::SparseSet<E>::_sparseAssurePage;
using _details::SparseSet<E>::_sparseGet;
using _details::SparseSet<E>::_sparseTryGet;

using utils::ReadonlyCounter<size_t>::_counter;
using _details::SparseSet<E>::_dense;
using _details::SparseSet<E>::_sparse;
using EntitiesViewT =
decltype(std::views::filter(*std::declval<const DenseContainer*>(), _details::EntityTraits::Version::hasNotNull)
);

// range with all valid entities in _dense
auto _entitiesForView() const noexcept;
static auto _emptyEntitiesForView() noexcept;
EntitiesViewT _entitiesForView() const noexcept;
static EntitiesViewT _emptyEntitiesForView() noexcept;
};

} // namespace arch::ecs::_details

#include "CommonComponentPool.hpp"
19 changes: 0 additions & 19 deletions include/ecs/CommonComponentPool.hpp

This file was deleted.

50 changes: 17 additions & 33 deletions include/ecs/ComponentPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ namespace arch::ecs {
/// @brief Pool for creating and destroying components
/// @details Uses sparse set data structure
/// @tparam C - component type
/// @tparam E - entity type
template<class C, class E>
class ComponentPool: public _details::CommonComponentPool<E> {
using Base = _details::CommonComponentPool<E>;
/// @tparam Entity - entity type
template<class C>
class ComponentPool: public _details::CommonComponentPool {
using Base = _details::CommonComponentPool;

public:

/// @brief ComponentTraits of component
using Traits = _details::ComponentTraits<C, E>;
using Traits = _details::ComponentTraits<C>;
/// @brief EntityTraits of entity
using ETraits = _details::EntityTraits<E>;
using ETraits = _details::EntityTraits;
/// @brief Entity type
using EntityT = E;
using EntityT = Entity;
/// @brief Id type
using IdT = typename ETraits::IdT;
/// @brief Version type
Expand All @@ -44,7 +44,7 @@ class ComponentPool: public _details::CommonComponentPool<E> {
using ConstGetReference = std::conditional_t<Traits::flag, bool, ConstReference>;

/// @brief Iterator of component pool
using Iterator = _details::ComponentPoolIterator<C, E>;
using Iterator = _details::ComponentPoolIterator<C>;
/// @brief Const iterator of component pool
using ConstIterator = const Iterator;
/// @brief Reverse iterator of component pool
Expand All @@ -70,10 +70,7 @@ class ComponentPool: public _details::CommonComponentPool<E> {
/// @param entity - entity to remove component from
/// @return Removed component
C removeComponent(const EntityT entity, MoveFlag) noexcept
requires(std::movable<C> && !_details::ComponentTraits<C, E>::flag);

using Base::contains;
using Base::count;
requires(std::movable<C> && !_details::ComponentTraits<C>::flag);

/// @brief Returns component of given entity
/// @details If component is non-flag and does not exist, the behavior is undefined
Expand All @@ -86,11 +83,11 @@ class ComponentPool: public _details::CommonComponentPool<E> {
/// @brief Returns optional with reference to component of given entity
/// @param entity - entity to get component of
std::optional<std::reference_wrapper<C>> tryGet(const EntityT entity) noexcept
requires(!_details::ComponentTraits<C, E>::flag);
requires(!_details::ComponentTraits<C>::flag);
/// @brief Returns optional with readonly reference to component of given entity
/// @param entity - entity to get component of
std::optional<std::reference_wrapper<const C>> tryGet(const EntityT entity) const noexcept
requires(!_details::ComponentTraits<C, E>::flag);
requires(!_details::ComponentTraits<C>::flag);

/// @brief Returns iterator to first (const entity, component) contained
Iterator begin() noexcept;
Expand All @@ -117,21 +114,14 @@ class ComponentPool: public _details::CommonComponentPool<E> {
/// @brief Returns reverse iterator to past-the-last (const entity, const component) contained in a reverse order
ConstReverseIterator crend() const noexcept;

using Base::_entitiesForView;

private:

using Base::_sparseAssure;
using Base::_sparseAssurePage;
using Base::_sparseGet;
using Base::_sparseTryGet;

friend arch::ecs::_details::ComponentPoolIterator<C, E>;
friend arch::ecs::_details::ComponentPoolIterator<C>;

//// returns entity of given id from sparse, assuring it's page exists
// E& _sparseAssure(const IdT id) noexcept;
// Entity& _sparseAssure(const IdT id) noexcept;
// returns new entity from dense, along with it's index
std::tuple<E&, size_t> _denseNew() noexcept;
std::tuple<Entity&, size_t> _denseNew() noexcept;
// returns pointer (likely invalid) to component of given id, can be used for placement-new or Traits::constructAt()
C* _componentAssure(const IdT id) noexcept;

Expand All @@ -140,11 +130,6 @@ class ComponentPool: public _details::CommonComponentPool<E> {
// finds index of last valid component, 0 if none
size_t _findLast() const noexcept;

// std::vector<std::unique_ptr<std::array<E, ETraits::pageSize>>> _sparse; // paged
// std::vector<E> _dense;
using Base::_counter;
using Base::_dense;
using Base::_sparse;
std::vector<C*> _components; // paged
size_t _listHead = 0;

Expand All @@ -162,12 +147,11 @@ class ComponentPool: public _details::CommonComponentPool<E> {
/// @brief Struct mimicing ComponentPool of any component type
/// @brief Used to achieve simmilar behavior as std::any
/// @details Usage conforms with Strict Aliasing Rule, making it safe
/// @tparam E - entity type
template<class E>
struct alignas(ComponentPool<void*, E>) ComponentPoolStorage {
/// @tparam Entity - entity type
struct alignas(ComponentPool<void*>) ComponentPoolStorage {
// void* is an arbitrary type
/// @brief Type of an arbitrary ComponentPool
using PoolT = ComponentPool<void*, E>;
using PoolT = ComponentPool<void*>;
/// @brief std::array with size and alignment of ComponentPool
/// @brief char is an exception to Strict Aliasing Rule
alignas(PoolT) std::array<char, sizeof(PoolT)> storage{};
Expand Down
Loading

0 comments on commit 45fe52a

Please sign in to comment.