Skip to content

Commit

Permalink
System Lifecycle
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubpa committed Nov 10, 2020
1 parent 57f71aa commit b0e52c9
Show file tree
Hide file tree
Showing 35 changed files with 433 additions and 198 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

project(UECS VERSION 0.13.3)
project(UECS VERSION 0.14.0)
message(STATUS "[Project] ${PROJECT_NAME}")

include(cmake/InitUCMake.cmake)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct MoverSystem {

int main() {
World w;
auto move = w.systemMngr.Register<MoverSystem>();
auto move = w.systemMngr.systemTraits.Register<MoverSystem>();
w.entityMngr.Create<Position, Velocity>();
w.systemMngr.Activate(move);
w.Update();
Expand Down
4 changes: 3 additions & 1 deletion doc/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
- [x] system base -> `System`
- [x] singleton
- [ ] doxygen
- [ ] lock ?
- [x] system traits

### maybe support in future

Expand All @@ -44,7 +46,7 @@
### maybe not support in future

- [ ] shared component
- [ ] system group
- [ ] system group ?

## tool

Expand Down
3 changes: 2 additions & 1 deletion include/UECS/CmptType.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ namespace Ubpa::UECS {
constexpr bool Valid() const noexcept { return hashcode == static_cast<size_t>(-1); }

template<typename Cmpt>
constexpr bool Is() const noexcept;
constexpr bool Is() const noexcept { return operator==(Of<Cmpt>); }
constexpr bool Is(std::string_view type_name) const noexcept { return operator==(CmptType{ type_name }); }

constexpr bool operator< (const CmptType& rhs) const noexcept { return hashcode < rhs.hashcode; }
constexpr bool operator<=(const CmptType& rhs) const noexcept { return hashcode <= rhs.hashcode; }
Expand Down
1 change: 1 addition & 0 deletions include/UECS/EntityMngr.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace Ubpa::UECS {
public:
EntityMngr();
EntityMngr(const EntityMngr& em);
EntityMngr(EntityMngr&&) noexcept = default;
~EntityMngr();

RTDCmptTraits cmptTraits;
Expand Down
86 changes: 42 additions & 44 deletions include/UECS/SystemMngr.h
Original file line number Diff line number Diff line change
@@ -1,55 +1,53 @@
#pragma once

#include <vector>
#include <map>
#include <set>
#include <functional>
#include <string>
#include "SystemTraits.h"

#include <unordered_set>

namespace Ubpa::UECS {
class Schedule;

class SystemMngr {
public:
SystemMngr() = default;
SystemMngr(const SystemMngr&);

using Func = std::function<void(Schedule&)>;
struct SystemInfo {
Func func;
std::string name;
};
const std::vector<SystemInfo>& GetSystems() const noexcept { return systems; }
const std::set<size_t>& GetActiveSystemIndices() const noexcept { return activeSystemIndices; }
const std::map<std::string_view, size_t>& GetNameToIndexMap() const noexcept { return name2idx; }

// if unregister, return static_cast<size_t>(-1)
size_t GetIndex(std::string_view name) const;
// name: nameof::nameof_type<System>
template<typename System>
size_t GetIndex() const;

void Clear() noexcept;

size_t Register(std::string name, Func);
// name: nameof::nameof_type<System>
// func: static void System::OnUpdate(Schedule&);
template<typename... Systems>
std::array<size_t, sizeof...(Systems)> Register();
void Unregister(size_t idx);
void Unregister(std::string_view name);
// name: nameof::nameof_type<System>
template<typename System>
void Unregister();

void Activate(size_t index);
void Deactivate(size_t index) noexcept;
SystemTraits systemTraits;

SystemMngr(World* w) : w{w}{}
SystemMngr(const SystemMngr& mngr, World* w) : systemTraits{ mngr.systemTraits }, w{ w } {}
SystemMngr(SystemMngr&& mngr, World* w) noexcept : systemTraits{ std::move(mngr.systemTraits) }, w{ w } {}
~SystemMngr();

// not alive -> create
void Create(size_t systemID);

// 1. not alive create -> create and activate
// 2. not active -> then activate
void Activate(size_t systemID);

// active -> deactavate
void Deactivate(size_t systemID);

// 1. active -> deactavite
// 2. alive -> destroy
void Destroy(size_t systemID);

bool IsAlive(size_t systemID) const;
bool IsActive(size_t systemID) const;

const auto& GetAliveSystemIDs() const noexcept { return aliveSystemIDs; }
const auto& GetActiveSystemsIDs() const noexcept { return activeSystemIDs; }

SystemMngr(const SystemMngr&) = delete;
SystemMngr(SystemMngr&&) noexcept = delete;
SystemMngr& operator=(const SystemMngr&) = delete;
SystemMngr& operator=(SystemMngr&&) noexcept = delete;

private:
std::vector<SystemInfo> systems;
std::vector<size_t> frees;
std::map<std::string_view, size_t> name2idx;
std::set<size_t> activeSystemIndices;
friend class World;
World* w;
void Update(size_t systemID, Schedule&) const;
void Clear();

std::unordered_set<size_t> aliveSystemIDs;
std::unordered_set<size_t> activeSystemIDs;
};
}

#include "detail/SystemMngr.inl"
78 changes: 78 additions & 0 deletions include/UECS/SystemTraits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#pragma once

#include <functional>
#include <unordered_map>
#include <array>

namespace Ubpa::UECS {
class World;
class Schedule;

class SystemTraits {
public:
// [life cycle]
// OnCreate
// |
// v
// OnActivate <---
// | |
// v |
// --> OnUpdate |
// | | |
// --------x |
// | |
// v |
// OnDeactivate |
// | |
// x----------
// |
// v
// OnDestroy
using OnCreate = std::function<void(World* )>;
using OnActivate = std::function<void(World* )>;
using OnUpdate = std::function<void(Schedule&)>;
using OnDeactivate = std::function<void(World* )>;
using OnDestroy = std::function<void(World* )>;

SystemTraits() = default;
SystemTraits(const SystemTraits&);
SystemTraits(SystemTraits&&) noexcept = default;

size_t Register(std::string name);
void RegisterOnCreate(size_t ID, OnCreate);
void RegisterOnActivate(size_t ID, OnActivate);
void RegisterOnUpdate(size_t ID, OnUpdate);
void RegisterOnDeactivate(size_t ID, OnDeactivate);
void RegisterOnDestroy(size_t ID, OnDestroy);

bool IsRegistered(size_t ID) const noexcept;
size_t GetID(std::string_view name) const;
std::string_view Nameof(size_t ID) const noexcept;
const auto& GetNameIDMap() const noexcept { return name2id; }

template<typename... Systems>
std::array<size_t, sizeof...(Systems)> Register();
template<typename System>
static std::string_view StaticNameof() noexcept;

private:
friend class SystemMngr;

void Create(size_t ID, World*) const;
void Activate(size_t ID, World*) const;
void Update(size_t ID, Schedule&) const;
void Deactivate(size_t ID, World*) const;
void Destroy(size_t ID, World*) const;

std::vector<std::string> names;
std::unordered_map<std::string_view, size_t> name2id;

std::unordered_map<size_t, OnCreate> createMap;
std::unordered_map<size_t, OnActivate> activateMap;
std::unordered_map<size_t, OnUpdate> updateMap;
std::unordered_map<size_t, OnDeactivate> deactivateMap;
std::unordered_map<size_t, OnDestroy> destroyMap;
};
}

#include "detail/SystemTraits.inl"
4 changes: 3 additions & 1 deletion include/UECS/World.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ namespace Ubpa::UECS {
// SystemMngr + EntityMngr
class World {
public:
World() = default;
World() : systemMngr{ this }{}
// not copy schedule, so you can't use DumpUpdateJobGraph() and GenUpdateFrameGraph() before Update()
World(const World&);
World(World&&) noexcept;
~World();

SystemMngr systemMngr;
EntityMngr entityMngr;
Expand Down
34 changes: 13 additions & 21 deletions include/UECS/detail/CmptType.inl
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
#pragma once

namespace Ubpa::UECS {
template<typename Cmpt>
constexpr bool CmptType::Is() const noexcept {
static_assert(!IsTaggedCmpt_v<Cmpt>);
return hashcode == TypeID<Cmpt>;
}
}

namespace std {
template<typename T>
struct hash;
}

template<>
struct hash<Ubpa::UECS::CmptType> {
constexpr size_t operator()(const Ubpa::UECS::CmptType& t) const noexcept {
return t.HashCode();
}
};
template<>
struct std::hash<Ubpa::UECS::CmptType> {
constexpr size_t operator()(const Ubpa::UECS::CmptType& t) const noexcept {
return t.HashCode();
}
};

template<>
struct hash<Ubpa::UECS::CmptAccessType> {
constexpr size_t operator()(const Ubpa::UECS::CmptAccessType& t) const noexcept {
return t.HashCode();
}
};
}
template<>
struct std::hash<Ubpa::UECS::CmptAccessType> {
constexpr size_t operator()(const Ubpa::UECS::CmptAccessType& t) const noexcept {
return t.HashCode();
}
};
20 changes: 0 additions & 20 deletions include/UECS/detail/SystemMngr.inl

This file was deleted.

46 changes: 46 additions & 0 deletions include/UECS/detail/SystemTraits.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include <nameof.hpp>

#include <UTemplate/Concept.h>

namespace Ubpa::UECS::detail {
template<typename System>
Concept(HaveOnCreate, static_cast<void(*)(World*)>(&System::OnCreate));
template<typename System>
Concept(HaveOnActivate, static_cast<void(*)(World*)>(&System::OnActivate));
template<typename System>
Concept(HaveOnUpdate, static_cast<void(*)(Schedule&)>(&System::OnUpdate));
template<typename System>
Concept(HaveOnDeactivate, static_cast<void(*)(World*)>(&System::OnDeactivate));
template<typename System>
Concept(HaveOnDestroy, static_cast<void(*)(World*)>(&System::OnDestroy));

template<typename System>
size_t Register(SystemTraits& traits) {
size_t ID = traits.Register(std::string{ SystemTraits::StaticNameof<System>() });
if constexpr (Require<HaveOnCreate, System>)
traits.RegisterOnCreate(ID, std::function{ static_cast<void(*)(World*)>(&System::OnCreate) });
if constexpr (Require<HaveOnActivate, System>)
traits.RegisterOnActivate(ID, std::function{ static_cast<void(*)(World*)>(&System::OnActivate) });
if constexpr (Require<HaveOnUpdate, System>)
traits.RegisterOnUpdate(ID, static_cast<void(*)(Schedule&)>(&System::OnUpdate));
if constexpr (Require<HaveOnDeactivate, System>)
traits.RegisterOnDeactivate(ID, std::function{ static_cast<void(*)(World*)>(&System::OnDeactivate) });
if constexpr (Require<HaveOnDeactivate, System>)
traits.RegisterOnDestroy(ID, std::function{ static_cast<void(*)(World*)>(&System::OnDestroy) });
return ID;
}
}

namespace Ubpa::UECS {
template<typename... Systems>
std::array<size_t, sizeof...(Systems)> SystemTraits::Register() {
return { detail::Register<Systems>(*this)... };
}

template<typename System>
std::string_view SystemTraits::StaticNameof() noexcept {
return nameof::nameof_type<System>();
}
}
1 change: 0 additions & 1 deletion src/core/EntityMngr.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <UECS/EntityMngr.h>

#include <UECS/detail/SystemFunc.h>
#include <UECS/World.h>
#include <UECS/IListener.h>

using namespace Ubpa::UECS;
Expand Down
Loading

0 comments on commit b0e52c9

Please sign in to comment.