Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubpa committed Aug 12, 2020
1 parent e2d4964 commit b4070c3
Show file tree
Hide file tree
Showing 12 changed files with 79 additions and 72 deletions.
2 changes: 1 addition & 1 deletion include/UECS/ChunkView.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Ubpa::UECS {

bool Contains(CmptType) const;

// if not contain, return nullptr
// nullptr if not contain
void* GetCmptArray(CmptType) const;
template<typename Cmpt>
Cmpt* GetCmptArray() const { return reinterpret_cast<Cmpt*>(GetCmptArray(CmptType::Of<Cmpt>)); }
Expand Down
15 changes: 8 additions & 7 deletions include/UECS/EntityMngr.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ namespace Ubpa::UECS {
// [API]
// - Entity: Create, Instantiate, Destroy, Exist
// - Component: Attach, Emplace, Detach, Have, Get, Components
// - Singleton: IsSingleton, GetSingletonEntity, GetSingleton
// - other: EntityNum, AddCommand
// [important]
// - API with CmptType need RTDCmptTraits to get {size|alignment|lifecycle function} (throw std::logic_error)
// - some API with CmptType need RTDCmptTraits to get {size|alignment|lifecycle function} (throw std::logic_error)
// - API with Entity require Entity exist (throw std::invalid_argument)
class EntityMngr {
public:
Expand Down Expand Up @@ -50,8 +51,10 @@ namespace Ubpa::UECS {

bool Have(Entity, CmptType) const;

// nullptr if not singleton
template<typename Cmpt>
Cmpt* Get(Entity) const;
// nullptr if not singleton
CmptPtr Get(Entity, CmptType) const;

std::vector<CmptPtr> Components(Entity) const;
Expand All @@ -66,13 +69,10 @@ namespace Ubpa::UECS {

bool IsSingleton(CmptType) const;
Entity GetSingletonEntity(CmptType) const;
CmptPtr GetSingleton(CmptType) const;
// nullptr if not singleton
CmptPtr GetIfSingleton(CmptType) const;
CmptPtr GetSingleton(CmptType) const;
template<typename Cmpt>
Cmpt* GetSingleton() const { return GetSingleton(CmptType::Of<Cmpt>).As<Cmpt>(); }
template<typename Cmpt>
Cmpt* GetIfSingleton() const { return GetIfSingleton(CmptType::Of<Cmpt>).As<Cmpt>(); }

void Accept(IListener* listener) const;

Expand All @@ -89,9 +89,10 @@ namespace Ubpa::UECS {
// types not contain Entity
Archetype* GetOrCreateArchetypeOf(const CmptType* types, size_t num);

// return original archetype
template<typename... Cmpts>
void AttachWithoutInit(Entity);
void AttachWithoutInit(Entity, const CmptType* types, size_t num);
Archetype* AttachWithoutInit(Entity);
Archetype* AttachWithoutInit(Entity, const CmptType* types, size_t num);

const std::set<Archetype*>& QueryArchetypes(const EntityQuery& query) const;
mutable std::unordered_map<EntityQuery, std::set<Archetype*>> queryCache;
Expand Down
1 change: 1 addition & 0 deletions include/UECS/RTDCmptTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace Ubpa::UECS {

size_t Sizeof(CmptType) const;
size_t Alignof(CmptType) const;
void DefaultConstruct(CmptType, void* cmpt) const;
void CopyConstruct(CmptType, void* dst, void* src) const;
void MoveConstruct(CmptType, void* dst, void* src) const;
void MoveAssign(CmptType, void* dst, void* src) const;
Expand Down
6 changes: 3 additions & 3 deletions include/UECS/detail/Archetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ namespace Ubpa::UECS {
std::tuple<std::vector<Entity*>, std::vector<std::vector<CmptPtr>>, std::vector<size_t>>
Locate(const CmptLocator& locator) const;

// nullptr if not contains
void* Locate(size_t chunkIdx, CmptType) const;

Chunk* GetChunk(size_t chunkIdx) const { return chunks[chunkIdx]; }

// nullptr if not contains
void* At(CmptType, size_t idx) const;

// nullptr if not contains
template<typename Cmpt>
Cmpt* At(size_t idx) const{ return reinterpret_cast<Cmpt*>(At(CmptType::Of<Cmpt>, idx)); }

Expand Down Expand Up @@ -78,9 +81,6 @@ namespace Ubpa::UECS {
const CmptTypeSet& GetCmptTypeSet() const noexcept { return types; }
const RTSCmptTraits& GetRTSCmptTraits() const noexcept { return cmptTraits; }

// no Entity
size_t CmptNum() const noexcept { return types.data.size() - 1; }

size_t EntityNum() const noexcept { return entityNum; }
size_t EntityNumOfChunk(size_t chunkIdx) const noexcept;
size_t ChunkNum() const noexcept { return chunks.size(); }
Expand Down
26 changes: 16 additions & 10 deletions include/UECS/detail/Archetype.inl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Ubpa::UECS {
types(GenCmptTypeSet<Cmpts...>())
{
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"Archetype::Archetype: <Cmpts>... must be different");
"<Cmpts>... must be different");
cmptTraits.Register<Entity>();
(cmptTraits.Register<Cmpts>(), ...);
SetLayout();
Expand All @@ -19,12 +19,14 @@ namespace Ubpa::UECS {
template<typename... Cmpts>
Archetype* Archetype::Add(const Archetype* from) {
static_assert(sizeof...(Cmpts) > 0);
assert(((!from->types.Contains(CmptType::Of<Cmpts>)) &&...));
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"<Cmpts>... must be different");
assert(!from->types.Contains(std::array{ CmptType::Of<Cmpts>... }));

Archetype* rst = new Archetype{ from->entityMngr };

rst->types = from->types;
rst->types.data.insert(CmptType::Of<Cmpts>...);
(rst->types.data.insert(CmptType::Of<Cmpts>), ...);
rst->cmptTraits = from->cmptTraits;
(rst->cmptTraits.Register<Cmpts>(), ...);

Expand All @@ -35,30 +37,34 @@ namespace Ubpa::UECS {

template<typename... Cmpts>
std::tuple<size_t, std::tuple<Cmpts *...>> Archetype::Create(Entity e) {
assert((types.Contains(CmptType::Of<Cmpts>) &&...) && types.data.size() == 1 + sizeof...(Cmpts));
static_assert((std::is_constructible_v<Cmpts> &&...),
"Archetype::Create: <Cmpts> isn't constructible");
"<Cmpts> isn't constructible");
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"Archetype::Create: <Cmpts>... must be different");
"<Cmpts>... must be different");

assert((types.Contains(CmptType::Of<Cmpts>) &&...) && types.data.size() == 1 + sizeof...(Cmpts));

size_t idx = RequestBuffer();
size_t idxInChunk = idx % chunkCapacity;
byte* buffer = chunks[idx / chunkCapacity]->Data();

new(buffer + Offsetof(CmptType::Of<Entity>) + idxInChunk * sizeof(Entity))Entity(e);

std::tuple<Cmpts*...> cmpts = { new(buffer + Offsetof(CmptType::Of<Cmpts>) + idxInChunk * sizeof(Cmpts))Cmpts... };
std::tuple cmpts = { new(buffer + Offsetof(CmptType::Of<Cmpts>) + idxInChunk * sizeof(Cmpts))Cmpts... };

return { idx,cmpts };
}

template<typename... Cmpts>
CmptTypeSet Archetype::GenCmptTypeSet() {
if constexpr(sizeof...(Cmpts) == 0)
return Archetype::GenCmptTypeSet(nullptr, 0);
else {
if constexpr (sizeof...(Cmpts) > 0) {
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"<Cmpts>... must be different");

constexpr std::array types = { CmptType::Of<Cmpts>... };
return Archetype::GenCmptTypeSet(types.data(), types.size());
}
else
return Archetype::GenCmptTypeSet(nullptr, 0);
}
}
2 changes: 1 addition & 1 deletion include/UECS/detail/CmptsLocator.inl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Ubpa::UECS::detail {
template<typename... Cmpts>
CmptLocator GenerateCmptLocator(TypeList<Cmpts...>) {
if constexpr (sizeof...(Cmpts) > 0) {
constexpr std::array<CmptType, sizeof...(Cmpts)> types{ CmptType::Of<Cmpts>... };
constexpr std::array types{ CmptType::Of<Cmpts>... };
return CmptLocator{ types.data(), types.size() };
}
else
Expand Down
32 changes: 12 additions & 20 deletions include/UECS/detail/EntityMngr.inl
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
namespace Ubpa::UECS {
template<typename... Cmpts>
Archetype* EntityMngr::GetOrCreateArchetypeOf() {
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"EntityMngr::GetOrCreateArchetypeOf: <Cmpts>... must be different");

const auto typeset = Archetype::GenCmptTypeSet<Cmpts...>();
auto target = ts2a.find(typeset);
if(target != ts2a.end())
Expand All @@ -28,8 +25,6 @@ namespace Ubpa::UECS {

template<typename... Cmpts>
std::tuple<Entity, Cmpts*...> EntityMngr::Create() {
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"EntityMngr::Create: <Cmpts>... must be different");
Archetype* archetype = GetOrCreateArchetypeOf<Cmpts...>();
size_t entityIndex = RequestEntityFreeEntry();
EntityInfo& info = entityTable[entityIndex];
Expand All @@ -41,18 +36,15 @@ namespace Ubpa::UECS {
}

template<typename... Cmpts>
void EntityMngr::AttachWithoutInit(Entity e) {
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
"EntityMngr::AttachWithoutInit: <Cmpts>... must be different");
Archetype* EntityMngr::AttachWithoutInit(Entity e) {
if (!Exist(e)) throw std::invalid_argument("Entity is invalid");

auto& info = entityTable[e.Idx()];
Archetype* srcArchetype = info.archetype;
size_t srcIdxInArchetype = info.idxInArchetype;

const auto& srcCmptTypeSet = srcArchetype->GetCmptTypeSet();
auto dstCmptTypeSet = srcCmptTypeSet;
dstCmptTypeSet.data.insert(CmptType::Of<Cmpts>...);
(dstCmptTypeSet.data.insert(CmptType::Of<Cmpts>), ...);

// get dstArchetype
Archetype* dstArchetype;
Expand All @@ -66,13 +58,14 @@ namespace Ubpa::UECS {
}
ts2a.emplace(std::move(dstCmptTypeSet), std::unique_ptr<Archetype>{ dstArchetype });
}
else
else {
dstArchetype = target->second.get();

if (dstArchetype == srcArchetype)
return;
if (dstArchetype == srcArchetype)
return srcArchetype;
}

// move src to dst
size_t srcIdxInArchetype = info.idxInArchetype;
size_t dstIdxInArchetype = dstArchetype->RequestBuffer();

auto srcCmptTraits = srcArchetype->GetRTSCmptTraits();
Expand All @@ -89,17 +82,16 @@ namespace Ubpa::UECS {

info.archetype = dstArchetype;
info.idxInArchetype = dstIdxInArchetype;

return srcArchetype;
}

template<typename... Cmpts>
std::tuple<Cmpts*...> EntityMngr::Attach(Entity e) {
static_assert((std::is_default_constructible_v<Cmpts> &&...),
"EntityMngr::Attach: <Cmpts> isn't default constructible");

using CmptList = TypeList<Cmpts...>;
const auto& cmptTypes = entityTable[e.Idx()].archetype->GetCmptTypeSet();
auto origArchetype = AttachWithoutInit<Cmpts...>(e);
const auto& cmptTypes = origArchetype->GetCmptTypeSet();
std::array needAttach = { !cmptTypes.Contains(CmptType::Of<Cmpts>)... };
AttachWithoutInit<Cmpts...>(e);
const auto& new_info = entityTable[e.Idx()];
std::tuple cmpts{ new_info.archetype->At<Cmpts>(new_info.idxInArchetype)... };
((std::get<Find_v<CmptList, Cmpts>>(needAttach) ? new(std::get<Cmpts*>(cmpts))Cmpts : nullptr), ...);
Expand All @@ -111,7 +103,7 @@ namespace Ubpa::UECS {
Cmpt* EntityMngr::Emplace(Entity e, Args&&... args) {
static_assert(std::is_constructible_v<Cmpt, Args...>
|| is_list_initializable_v<Cmpt, Args...>,
"EntityMngr::Emplace: <Cmpt> isn't constructible/list_initializable with Args...");
"<Cmpt> isn't constructible/list_initializable with Args...");

if (!Have(e, CmptType::Of<Cmpt>)) {
AttachWithoutInit<Cmpt>(e);
Expand Down
7 changes: 7 additions & 0 deletions include/UECS/detail/RTDCmptTraits.inl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ namespace Ubpa::UECS {
return alignments.find(type)->second;
}

inline void RTDCmptTraits::DefaultConstruct(CmptType type, void* cmpt) const {
auto target = default_constructors.find(type);

if (target != default_constructors.end())
target->second(cmpt);
}

inline void RTDCmptTraits::CopyConstruct(CmptType type, void* dst, void* src) const {
auto target = copy_constructors.find(type);

Expand Down
2 changes: 1 addition & 1 deletion include/UECS/detail/SingletonLocator.inl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Ubpa::UECS::detail {
template<typename... Singletons>
SingletonLocator GenerateSingletonLocator(TypeList<Singletons...>) {
if constexpr (sizeof...(Singletons) > 0) {
constexpr std::array<CmptType, sizeof...(Singletons)> types{ CmptType::Of<Singletons>... };
constexpr std::array types{ CmptType::Of<Singletons>... };
return SingletonLocator{ types.data(), types.size() };
}
else
Expand Down
10 changes: 7 additions & 3 deletions src/core/Archetype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Archetype* Archetype::New(EntityMngr* entityMngr, const CmptType* types, size_t

Archetype* Archetype::Add(const Archetype* from, const CmptType* types, size_t num) {
assert(NotContainEntity(types, num));
assert(!from->types.ContainsAny(types, num));
assert(!from->types.Contains(types, num));

Archetype* rst = new Archetype{ from->entityMngr };

Expand Down Expand Up @@ -126,7 +126,9 @@ size_t Archetype::RequestBuffer() {

void* Archetype::At(CmptType type, size_t idx) const {
assert(idx < entityNum);
assert(types.Contains(type));

if (!types.Contains(type))
return nullptr;

size_t size = cmptTraits.Sizeof(type);
size_t offset = Offsetof(type);
Expand Down Expand Up @@ -192,8 +194,10 @@ tuple<vector<Entity*>, vector<vector<CmptPtr>>, vector<size_t>> Archetype::Locat
}

void* Archetype::Locate(size_t chunkIdx, CmptType t) const {
assert(types.Contains(t));
assert(chunkIdx < chunks.size());
if (!types.Contains(t))
return nullptr;

auto buffer = chunks[chunkIdx]->Data();
return buffer + Offsetof(t);
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/ChunkView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using namespace Ubpa::UECS;

void* ChunkView::GetCmptArray(CmptType t) const {
return Contains(t) ? archetype->Locate(chunkIdx, t) : nullptr;
return archetype->Locate(chunkIdx, t);
}

size_t ChunkView::EntityNum() const noexcept {
Expand Down
Loading

0 comments on commit b4070c3

Please sign in to comment.