Implemented ComponentPool and initial tests for it
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
#ifndef ComponentInfo_h__
|
||||||
|
#define ComponentInfo_h__
|
||||||
|
|
||||||
#include "../Common.h"
|
#include "../Common.h"
|
||||||
|
|
||||||
struct ComponentInfo
|
struct ComponentInfo
|
||||||
@@ -5,11 +8,15 @@ struct ComponentInfo
|
|||||||
struct Meta_t
|
struct Meta_t
|
||||||
{
|
{
|
||||||
std::string Annotation;
|
std::string Annotation;
|
||||||
int Allocation = 0;
|
unsigned int Allocation = 0;
|
||||||
|
unsigned int Stride = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string Name;
|
std::string Name;
|
||||||
std::unordered_map<std::string, std::string> FieldTypes;
|
std::unordered_map<std::string, std::string> FieldTypes;
|
||||||
std::unordered_map<std::string, unsigned int> FieldOffsets;
|
std::unordered_map<std::string, unsigned int> FieldOffsets;
|
||||||
Meta_t Meta;
|
Meta_t Meta;
|
||||||
|
std::shared_ptr<char*> Defaults = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,125 @@
|
|||||||
|
#ifndef ComponentPool_h__
|
||||||
|
#define ComponentPool_h__
|
||||||
|
|
||||||
|
#include "MemoryPool.h"
|
||||||
|
#include "ComponentInfo.h"
|
||||||
|
#include "ComponentWrapper.h"
|
||||||
|
|
||||||
|
class ComponentPoolForwardIterator
|
||||||
|
: public std::iterator<std::forward_iterator_tag, ComponentWrapper>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ComponentPoolForwardIterator(const ComponentInfo& componentInfo, const MemoryPool<char>::iterator begin, const MemoryPool<char>::iterator end)
|
||||||
|
: m_ComponentInfo(componentInfo)
|
||||||
|
, m_MemoryPoolIterator(begin)
|
||||||
|
, m_MemoryPoolEnd(end)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ComponentPoolForwardIterator(const ComponentPoolForwardIterator& other) = default;
|
||||||
|
ComponentPoolForwardIterator(ComponentPoolForwardIterator&& other) = default;
|
||||||
|
~ComponentPoolForwardIterator() = default;
|
||||||
|
ComponentPoolForwardIterator& operator= (const ComponentPoolForwardIterator& other) = default;
|
||||||
|
|
||||||
|
ComponentPoolForwardIterator& operator++()
|
||||||
|
{
|
||||||
|
++m_MemoryPoolIterator;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentPoolForwardIterator& operator++(int)
|
||||||
|
{
|
||||||
|
ComponentPoolForwardIterator copyIter(*this);
|
||||||
|
operator++();
|
||||||
|
return copyIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const ComponentPoolForwardIterator& other) const
|
||||||
|
{
|
||||||
|
return m_MemoryPoolIterator != other.m_MemoryPoolIterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const ComponentPoolForwardIterator& other) const
|
||||||
|
{
|
||||||
|
return m_MemoryPoolIterator == other.m_MemoryPoolIterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentWrapper operator* () const
|
||||||
|
{
|
||||||
|
char* data = &(*m_MemoryPoolIterator);
|
||||||
|
ComponentWrapper wrapper(m_ComponentInfo, data);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ComponentWrapper* operator-> () const
|
||||||
|
//{
|
||||||
|
// return &(*m_MemoryPoolIterator);
|
||||||
|
//}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ComponentInfo& m_ComponentInfo;
|
||||||
|
MemoryPool<char>::iterator m_MemoryPoolIterator;
|
||||||
|
const MemoryPool<char>::iterator m_MemoryPoolEnd;
|
||||||
|
};
|
||||||
|
|
||||||
class ComponentPool
|
class ComponentPool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ComponentPool() { }
|
typedef ComponentPoolForwardIterator iterator;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef size_t size_type;
|
||||||
|
typedef ComponentWrapper value_type;
|
||||||
|
typedef ComponentWrapper* pointer;
|
||||||
|
typedef ComponentWrapper& reference;
|
||||||
|
|
||||||
|
ComponentPool(const ComponentInfo& ci)
|
||||||
|
: m_ComponentInfo(ci)
|
||||||
|
, m_Pool(ci.Meta.Allocation, ci.Meta.Stride)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ComponentPool(const ComponentPool& other) = delete;
|
||||||
|
ComponentPool(const ComponentPool&& other) = delete;
|
||||||
|
|
||||||
|
ComponentWrapper New()
|
||||||
|
{
|
||||||
|
char* data = m_Pool.Allocate();
|
||||||
|
return ComponentWrapper(m_ComponentInfo, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delete(ComponentWrapper& component)
|
||||||
|
{
|
||||||
|
m_Pool.Free(component.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() const
|
||||||
|
{
|
||||||
|
return iterator(m_ComponentInfo, m_Pool.begin(), m_Pool.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() const
|
||||||
|
{
|
||||||
|
return iterator(m_ComponentInfo, m_Pool.end(), m_Pool.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
//Dumps information about what the pool memory looks like right now
|
||||||
|
//into an output stream (e.g. file/std::cout, anything that has an operator<<)
|
||||||
|
//Interpret the data in the memory as InterpretType.
|
||||||
|
template <typename InterpretType = char, typename OutStream>
|
||||||
|
void Dump(OutStream& out) const
|
||||||
|
{
|
||||||
|
m_Pool.Dump<InterpretType>(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Dumps information about what the pool memory looks like right now
|
||||||
|
//into std::cout. Interpret the data in the memory as InterpretType.
|
||||||
|
template <typename InterpretType = char>
|
||||||
|
void Dump() const
|
||||||
|
{
|
||||||
|
m_Pool.Dump<InterpretType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ComponentInfo m_ComponentInfo;
|
||||||
|
MemoryPool<char> m_Pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,24 +2,25 @@
|
|||||||
#define Component_h__
|
#define Component_h__
|
||||||
|
|
||||||
#include "../Common.h"
|
#include "../Common.h"
|
||||||
|
#include "Entity.h"
|
||||||
#include "ComponentInfo.h"
|
#include "ComponentInfo.h"
|
||||||
|
|
||||||
struct Component
|
struct ComponentWrapper
|
||||||
{
|
{
|
||||||
Component(const unsigned int entityID, const ComponentInfo* componentInfo, char* data)
|
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
|
||||||
: EntityID(entityID)
|
: EntityID(*reinterpret_cast<::EntityID*>(data))
|
||||||
, Info(componentInfo)
|
, Info(componentInfo)
|
||||||
, Data(data)
|
, Data(data)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
const unsigned int EntityID;
|
::EntityID& EntityID;
|
||||||
const ComponentInfo* Info;
|
const ComponentInfo& Info;
|
||||||
char* Data;
|
char* Data;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& Property(std::string name)
|
T& Property(std::string name)
|
||||||
{
|
{
|
||||||
unsigned int offset=Info->FieldOffsets.at(name);
|
unsigned int offset = Info.FieldOffsets.at(name);
|
||||||
return *reinterpret_cast<T*>(&Data[offset]);
|
return *reinterpret_cast<T*>(&Data[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,14 +35,14 @@ struct Component
|
|||||||
|
|
||||||
struct SubscriptProxy
|
struct SubscriptProxy
|
||||||
{
|
{
|
||||||
friend struct Component;
|
friend struct ComponentWrapper;
|
||||||
private:
|
private:
|
||||||
SubscriptProxy(Component* component, std::string& propertyName)
|
SubscriptProxy(ComponentWrapper* component, std::string& propertyName)
|
||||||
: m_Component(component)
|
: m_Component(component)
|
||||||
, m_PropertyName(propertyName)
|
, m_PropertyName(propertyName)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Component* m_Component;
|
ComponentWrapper* m_Component;
|
||||||
std::string& m_PropertyName;
|
std::string& m_PropertyName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <xercesc/framework/XMLValidator.hpp>
|
#include <xercesc/framework/XMLValidator.hpp>
|
||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Component.h"
|
#include "ComponentWrapper.h"
|
||||||
|
|
||||||
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
|
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
|
||||||
{
|
{
|
||||||
@@ -111,17 +111,17 @@ struct ComponentPool
|
|||||||
char* Data = nullptr;
|
char* Data = nullptr;
|
||||||
|
|
||||||
// TODO: Iterators
|
// TODO: Iterators
|
||||||
Component at(unsigned int index)
|
ComponentWrapper at(unsigned int index)
|
||||||
{
|
{
|
||||||
// TODO: EntityID
|
// TODO: EntityID
|
||||||
return Component(0, &Info, Data + (index*Stride));
|
return ComponentWrapper(0, &Info, Data + (index*Stride));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EntityParser
|
class EntityFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EntityParser(std::string entityFile)
|
EntityFactory(std::string entityFile)
|
||||||
: m_EntityFile(entityFile)
|
: m_EntityFile(entityFile)
|
||||||
{
|
{
|
||||||
using namespace xercesc;
|
using namespace xercesc;
|
||||||
@@ -147,7 +147,7 @@ public:
|
|||||||
m_DOMParser->cacheGrammarFromParse(true);
|
m_DOMParser->cacheGrammarFromParse(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
~EntityParser()
|
~EntityFactory()
|
||||||
{
|
{
|
||||||
using namespace xercesc;
|
using namespace xercesc;
|
||||||
|
|
||||||
@@ -344,6 +344,7 @@ private:
|
|||||||
fieldOffset += getTypeStride(type);
|
fieldOffset += getTypeStride(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compInfo.Meta.Stride = fieldOffset;
|
||||||
m_ComponentInfo[compInfo.Name] = compInfo;
|
m_ComponentInfo[compInfo.Name] = compInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -476,4 +477,4 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int EntityParser::InstanceCount = 0;
|
unsigned int EntityFactory::InstanceCount = 0;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
|
class EntityFile : public Resource
|
||||||
|
{
|
||||||
|
friend class ResourceManager;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EntityFile(std::string path);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef T* pointer;
|
typedef T* pointer;
|
||||||
typedef T& reference;
|
typedef T& reference;
|
||||||
|
|
||||||
MemoryPool()
|
MemoryPool()
|
||||||
: m_StartAddress(nullptr)
|
: m_StartAddress(nullptr)
|
||||||
, m_SlotIsAllocated()
|
, m_SlotIsAllocated()
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
#ifndef World_h__
|
||||||
|
#define World_h__
|
||||||
|
|
||||||
|
#include "../Common.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "ComponentPool.h"
|
||||||
|
|
||||||
class World
|
class World
|
||||||
{
|
{
|
||||||
@@ -7,5 +13,21 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~World()
|
||||||
|
{
|
||||||
|
// foreach (m_ComponentPools...
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocateComponentPool(ComponentInfo& ci)
|
||||||
|
{
|
||||||
|
auto pool = new ComponentPool(ci);
|
||||||
|
m_ComponentPools[ci.Name] = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddComponent(EntityID entity, std::string componentType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include "Core/ComponentPool.h"
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ComponentPoolTest)
|
||||||
|
{
|
||||||
|
ComponentInfo ci;
|
||||||
|
ci.Name = "Test";
|
||||||
|
ci.FieldTypes["Field"] = "int";
|
||||||
|
ci.FieldOffsets["Field"] = sizeof(EntityID);
|
||||||
|
ci.Meta.Allocation = 4;
|
||||||
|
ci.Meta.Stride = sizeof(EntityID) + sizeof(int);
|
||||||
|
|
||||||
|
ComponentPool pool(ci);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
ComponentWrapper c = pool.New();
|
||||||
|
c.EntityID = i;
|
||||||
|
unsigned int offset = c.Info.FieldOffsets.at("Field");
|
||||||
|
memcpy(&c.Data[offset], &i, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto& c : pool) {
|
||||||
|
BOOST_CHECK(c.EntityID == i);
|
||||||
|
int field = c.Property<int>("Field");
|
||||||
|
BOOST_CHECK(field == i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user