This repository has been archived by the owner on Jun 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Incomplete Index Component System (ICS) (#2)
* feat(engine): add typeMap utility and test * refactor: replace static_assert with concepts require * refactor: rename typeMap to TypeMap * feat: add component concept, default and test * feat: add component vector container * chore: split up cmake build files to libraries * fix: move compVec template definition into header file * fix: missing unique_ptr initialisation for compVec * feat: add remove function to compVec and add isActiveCheck * refactor: reorder compVec methods * feat: add index concept * fix: remove typeMap base class and replace with any type * feat: add .has member test to typeMap * feat: add manager with sample addComponent and addIndex * fix: add component archetype so index only has one template param * chore: add more tests with runtime assertions concepts can be checked using Concept<Type> instead of creating a function * chore: remove test set_property in CMakeLists * fix: fix googletet configuration to remove version warning * chore: remove parent and child component in compVec test Parent and child component is replaced with a generic test component * refactor: rename Manager to ICSManager * fix: CMakeLists Manager was not renamed to ICSManager
- Loading branch information
Showing
14 changed files
with
456 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#ifndef BENTOBOX_ICSMANAGER_H | ||
#define BENTOBOX_ICSMANAGER_H | ||
|
||
#include <memory> | ||
#include <ics/index.h> | ||
#include <ics/component.h> | ||
#include <ics/compVec.h> | ||
#include <util/typeMap.h> | ||
|
||
namespace { | ||
template<ics::Component C> | ||
using CompContainer = ics::CompVec<C>; | ||
} | ||
|
||
class ICSManager { | ||
private: | ||
std::unique_ptr<util::TypeMap> indexes; | ||
std::unique_ptr<util::TypeMap> components; | ||
public: | ||
template<ics::Component C> | ||
void addComponent(C c) { | ||
if (components->has<CompContainer<C>>()) { | ||
// The container already exists | ||
// TODO: test that this actually updates the container value | ||
auto container = components->at<CompContainer<C>>(); | ||
container.add(c); | ||
} else { | ||
// The container does not exist | ||
auto container = CompContainer<C>(); | ||
container.add(c); | ||
components->insert(container); | ||
} | ||
} | ||
|
||
template<ics::Component C, ics::Index I> | ||
void addIndex(I i) { | ||
if (indexes->has<I>()) { | ||
// TODO: Make a better error | ||
throw std::logic_error("ICSManager::addIndex: attempting to replace existing index"); | ||
} else { | ||
indexes->insert(i); | ||
} | ||
} | ||
}; | ||
|
||
#endif //BENTOBOX_ICSMANAGER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
SET(LIB_NAME ics) | ||
SET(SOURCES component.h compVec.h index.h) | ||
SET(TESTS component.test.cpp compVec.test.cpp index.test.cpp) | ||
|
||
add_library( | ||
${LIB_NAME} | ||
${SOURCES} | ||
) | ||
|
||
add_library( | ||
${LIB_NAME}-test | ||
${SOURCES} | ||
${TESTS} | ||
) | ||
|
||
# Cmake could not determine the language used from the files | ||
# https://stackoverflow.com/questions/11801186/cmake-unable-to-determine-linker-language-with-c | ||
set_target_properties(${LIB_NAME} PROPERTIES LINKER_LANGUAGE CXX) | ||
set_target_properties(${LIB_NAME}-test PROPERTIES LINKER_LANGUAGE CXX) | ||
|
||
target_include_directories(${LIB_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") | ||
target_include_directories(${LIB_NAME}-test PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") | ||
|
||
# Google test | ||
target_link_libraries("${LIB_NAME}-test" PRIVATE gtest) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#ifndef BENTOBOX_COMPVEC_H | ||
#define BENTOBOX_COMPVEC_H | ||
|
||
#include <vector> | ||
#include <queue> | ||
#include <memory> | ||
#include <typeindex> | ||
#include <iostream> | ||
|
||
#include "component.h" | ||
|
||
namespace ics { | ||
template<Component C> | ||
class CompVec { | ||
public: | ||
typedef typename std::vector<C>::size_type size_type; | ||
private: | ||
std::unique_ptr<std::queue<size_type>> inactiveCompIdx = std::make_unique<std::queue<size_type>>(); | ||
std::unique_ptr<std::vector<C>> vecPtr = std::make_unique<std::vector<C>>(); | ||
protected: | ||
void isActiveCheck(size_type idx) const; | ||
public: | ||
size_type add(const C& val); | ||
void remove(size_type idx); | ||
|
||
C& at(size_type idx) const; | ||
C& operator[](size_type idx); | ||
const C& operator[](size_type idx) const; | ||
}; | ||
|
||
template<Component C> | ||
void CompVec<C>::isActiveCheck(size_type idx) const { | ||
if (!this->vecPtr->at(idx).isActive) { | ||
// TODO: format the index into the string | ||
throw std::out_of_range("compVec::isActiveCheck: component at index is inactive"); | ||
} | ||
} | ||
|
||
template<Component C> | ||
typename CompVec<C>::size_type CompVec<C>::add(const C& val) { | ||
if (!this->inactiveCompIdx->empty()) { | ||
// Reuse old component space | ||
CompVec<C>::size_type insertIdx = this->inactiveCompIdx->front(); | ||
this->vecPtr->at(insertIdx) = val; | ||
this->inactiveCompIdx->pop(); | ||
return insertIdx; | ||
} else { | ||
this->vecPtr->push_back(val); | ||
} | ||
} | ||
|
||
template<Component C> | ||
void CompVec<C>::remove(size_type idx) { | ||
// Mark component as deleted | ||
this->vecPtr->at(idx).isActive = false; | ||
this->inactiveCompIdx->push(idx); | ||
} | ||
|
||
template<Component C> | ||
C& CompVec<C>::at(CompVec<C>::size_type idx) const { | ||
this->isActiveCheck(idx); | ||
return this->vecPtr->at(idx); | ||
} | ||
|
||
template<Component C> | ||
const C& CompVec<C>::operator[](size_type idx) const { | ||
return this->at(idx); | ||
} | ||
|
||
template<Component C> | ||
C& CompVec<C>::operator[](size_type idx) { | ||
return this->at(idx); | ||
} | ||
} | ||
|
||
#endif //BENTOBOX_COMPVEC_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#include <gtest/gtest.h> | ||
#include "component.h" | ||
#include "compVec.h" | ||
|
||
#define TEST_SUITE CompVecTest | ||
|
||
using namespace ics; | ||
|
||
struct TestComp : public DefaultComponent { | ||
int height; | ||
}; | ||
|
||
TEST(TEST_SUITE, StoreAndRetrieve) { | ||
auto vec = CompVec<TestComp>(); | ||
vec.add(TestComp { true, 3 }); | ||
|
||
TestComp value = vec.at(0); | ||
ASSERT_EQ(value.height, 3); | ||
} | ||
|
||
TEST(TEST_SUITE, RetrieveNonExistentComponent) { | ||
auto vec = CompVec<TestComp>(); | ||
EXPECT_THROW( | ||
vec.at(0), | ||
std::out_of_range | ||
); | ||
} | ||
|
||
TEST(TEST_SUITE, ReuseDeletedComponent) { | ||
auto vec = CompVec<TestComp>(); | ||
|
||
// Create two elements | ||
auto firstElementIdx = vec.add(TestComp{ true, 3 }); | ||
vec.add(TestComp{ true, 3 }); | ||
|
||
// Remove the first | ||
vec.remove(firstElementIdx); | ||
|
||
// The first element's memory location should be reused | ||
auto newElement = TestComp { true, 3 }; | ||
auto newInsertIndex = vec.add(newElement); | ||
ASSERT_EQ(firstElementIdx, newInsertIndex); | ||
|
||
// The values should be the newly inserted component's values | ||
ics::Component auto firstElement = vec.at(firstElementIdx); | ||
ASSERT_EQ(firstElement, newElement); | ||
ASSERT_EQ(firstElement.height, 3); | ||
} | ||
|
||
TEST(TEST_SUITE, RetrieveDeletedComponent) { | ||
auto vec = CompVec<TestComp>(); | ||
auto idx = vec.add(TestComp{ true, 3 }); | ||
vec.remove(idx); | ||
EXPECT_THROW( | ||
vec.at(idx), | ||
std::out_of_range | ||
); | ||
EXPECT_THROW( | ||
vec[idx], | ||
std::out_of_range | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef BENTOBOX_COMPONENT_H | ||
#define BENTOBOX_COMPONENT_H | ||
|
||
#include <concepts> | ||
|
||
namespace ics { | ||
template<class T> | ||
concept Component = std::semiregular<T> | ||
&& std::same_as<decltype(T::isActive), bool>; | ||
|
||
// Needed for Index concept | ||
// See: https://stackoverflow.com/q/37655113/4428725 | ||
namespace archetypes { | ||
struct Component { | ||
bool isActive = true; | ||
bool operator==(const Component&) const = default; | ||
}; | ||
} | ||
|
||
static_assert(Component<archetypes::Component>); | ||
|
||
struct DefaultComponent { | ||
bool isActive = true; | ||
bool operator==(const DefaultComponent&) const = default; | ||
}; | ||
|
||
static_assert(Component<DefaultComponent>); | ||
} | ||
|
||
#endif //BENTOBOX_COMPONENT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#include <gtest/gtest.h> | ||
#include "component.h" | ||
|
||
#define TEST_SUITE Component | ||
|
||
using namespace ics; | ||
|
||
TEST(TEST_SUITE, DefaultComponentFulfillsConcept) { | ||
ASSERT_TRUE(Component<DefaultComponent>); | ||
} | ||
|
||
struct IncorrectNoIsactiveComponent { | ||
bool operator==(const IncorrectNoIsactiveComponent&) const = default; | ||
}; | ||
|
||
TEST(TEST_SUITE, RequireIsactive) { | ||
ASSERT_FALSE(Component<IncorrectNoIsactiveComponent>); | ||
} | ||
|
||
struct DerivedComp : public DefaultComponent { | ||
int height; | ||
char c; | ||
}; | ||
|
||
TEST(TEST_SUITE, DerivedComponentsEquivalence) { | ||
auto d1 = DerivedComp { | ||
.height = 3, | ||
.c = 'c', | ||
}; | ||
|
||
auto d2 = DerivedComp { | ||
.height = 3, | ||
.c = 'c', | ||
}; | ||
|
||
auto d3 = d1; | ||
|
||
ASSERT_EQ(d1, d2); | ||
ASSERT_EQ(d3, d1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#ifndef BENTOBOX_INDEX_H | ||
#define BENTOBOX_INDEX_H | ||
|
||
#include "component.h" | ||
|
||
namespace ics { | ||
template<class T> | ||
concept Index = requires(T a, archetypes::Component c) { | ||
{ a.template addComponent(c) } -> std::same_as<void>; | ||
{ a.template removeComponent(c) } -> std::same_as<void>; | ||
}; | ||
} | ||
|
||
#endif //BENTOBOX_INDEX_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include <gtest/gtest.h> | ||
#include "component.h" | ||
#include "index.h" | ||
|
||
#define TEST_SUITE Index | ||
|
||
using namespace ics; | ||
|
||
class CorrectIndex { | ||
public: | ||
template<Component C> | ||
void addComponent(C c) {}; | ||
|
||
template<Component C> | ||
void removeComponent(C c) {}; | ||
}; | ||
|
||
TEST(TEST_SUITE, HasAddAndRemoveComponent) { | ||
ASSERT_TRUE(Index<CorrectIndex>); | ||
} | ||
|
||
class IncorrectUnconstrainedIndex { | ||
public: | ||
template<typename C> | ||
void addComponent(C c) {}; | ||
|
||
template<typename C> | ||
void removeComponent(C c) {}; | ||
}; | ||
|
||
TEST(TEST_SUITE, DISABLED_DisallowsUnconstrainedTypenames) { | ||
ASSERT_FALSE(Index<IncorrectUnconstrainedIndex>); | ||
} | ||
|
||
template<Component C> | ||
class IncorrectNoTemplateMethodsIndex { | ||
public: | ||
void addComponent(C c) {}; | ||
|
||
void removeComponent(C c) {}; | ||
}; | ||
|
||
TEST(TEST_SUITE, DisallowsNonTemplateMethods) { | ||
ASSERT_FALSE(Index<IncorrectNoTemplateMethodsIndex<DefaultComponent>>); | ||
} |
Empty file.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.