Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36477abc63 |
@@ -5,12 +5,6 @@
|
|||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include <boost/shared_array.hpp>
|
#include <boost/shared_array.hpp>
|
||||||
|
|
||||||
enum class DirtySet
|
|
||||||
{
|
|
||||||
Transform,
|
|
||||||
Network
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ComponentInfo
|
struct ComponentInfo
|
||||||
{
|
{
|
||||||
typedef int EnumType;
|
typedef int EnumType;
|
||||||
|
|||||||
@@ -5,16 +5,15 @@
|
|||||||
#include "MemoryPool.h"
|
#include "MemoryPool.h"
|
||||||
#include "ComponentInfo.h"
|
#include "ComponentInfo.h"
|
||||||
#include "ComponentWrapper.h"
|
#include "ComponentWrapper.h"
|
||||||
|
#include "DirtySet.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ComponentPool;
|
||||||
class ComponentPoolForwardIterator
|
class ComponentPoolForwardIterator
|
||||||
: public std::iterator<std::forward_iterator_tag, ComponentWrapper>
|
: public std::iterator<std::forward_iterator_tag, ComponentWrapper>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ComponentPoolForwardIterator(const ComponentInfo& componentInfo, const MemoryPool<char>::iterator begin, const MemoryPool<char>::iterator end)
|
ComponentPoolForwardIterator(ComponentPool* pool);
|
||||||
: m_ComponentInfo(componentInfo)
|
|
||||||
, m_MemoryPoolIterator(begin)
|
|
||||||
, m_MemoryPoolEnd(end)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
ComponentPoolForwardIterator(const ComponentPoolForwardIterator& other) = default;
|
ComponentPoolForwardIterator(const ComponentPoolForwardIterator& other) = default;
|
||||||
ComponentPoolForwardIterator(ComponentPoolForwardIterator&& other) = default;
|
ComponentPoolForwardIterator(ComponentPoolForwardIterator&& other) = default;
|
||||||
@@ -27,6 +26,7 @@ public:
|
|||||||
ComponentWrapper operator*() const;
|
ComponentWrapper operator*() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ComponentPool* m_ComponentPool;
|
||||||
const ComponentInfo& m_ComponentInfo;
|
const ComponentInfo& m_ComponentInfo;
|
||||||
MemoryPool<char>::iterator m_MemoryPoolIterator;
|
MemoryPool<char>::iterator m_MemoryPoolIterator;
|
||||||
const MemoryPool<char>::iterator m_MemoryPoolEnd;
|
const MemoryPool<char>::iterator m_MemoryPoolEnd;
|
||||||
@@ -34,6 +34,7 @@ private:
|
|||||||
|
|
||||||
class ComponentPool
|
class ComponentPool
|
||||||
{
|
{
|
||||||
|
friend class ComponentPoolForwardIterator;
|
||||||
public:
|
public:
|
||||||
typedef ComponentPoolForwardIterator iterator;
|
typedef ComponentPoolForwardIterator iterator;
|
||||||
typedef ptrdiff_t difference_type;
|
typedef ptrdiff_t difference_type;
|
||||||
@@ -41,6 +42,7 @@ public:
|
|||||||
typedef ComponentWrapper value_type;
|
typedef ComponentWrapper value_type;
|
||||||
typedef ComponentWrapper* pointer;
|
typedef ComponentWrapper* pointer;
|
||||||
typedef ComponentWrapper& reference;
|
typedef ComponentWrapper& reference;
|
||||||
|
typedef std::unordered_map<EntityID, std::set<decltype(ComponentInfo::Field_t::Index)>> DirtySet_t;
|
||||||
|
|
||||||
ComponentPool(const ::ComponentInfo& ci)
|
ComponentPool(const ::ComponentInfo& ci)
|
||||||
: m_ComponentInfo(ci)
|
: m_ComponentInfo(ci)
|
||||||
@@ -61,8 +63,8 @@ public:
|
|||||||
// Delete a component and free its memory
|
// Delete a component and free its memory
|
||||||
void Delete(ComponentWrapper& wrapper);
|
void Delete(ComponentWrapper& wrapper);
|
||||||
|
|
||||||
iterator begin() const;
|
iterator begin();
|
||||||
iterator end() const;
|
iterator end();
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
|
||||||
//Dumps information about what the pool memory looks like right now
|
//Dumps information about what the pool memory looks like right now
|
||||||
@@ -80,6 +82,7 @@ private:
|
|||||||
::ComponentInfo m_ComponentInfo;
|
::ComponentInfo m_ComponentInfo;
|
||||||
MemoryPool<char> m_Pool;
|
MemoryPool<char> m_Pool;
|
||||||
std::unordered_map<EntityID, char*> m_EntityToComponent;
|
std::unordered_map<EntityID, char*> m_EntityToComponent;
|
||||||
|
DirtySet m_DirtySet;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -6,42 +6,52 @@
|
|||||||
#include "../Common.h"
|
#include "../Common.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "ComponentInfo.h"
|
#include "ComponentInfo.h"
|
||||||
|
#include "DirtySet.h"
|
||||||
#include "Util/Any.h"
|
#include "Util/Any.h"
|
||||||
|
|
||||||
template <typename T, typename Enable = void>
|
|
||||||
struct ComponentField { };
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct ComponentField<T, typename std::enable_if<std::is_trivially_copyable<T>::value>::type>
|
|
||||||
{
|
|
||||||
static T& Get(const ComponentInfo::Field_t& info, char* data) { return *reinterpret_cast<T*>(data); }
|
|
||||||
static void Set(const ComponentInfo::Field_t& info, char* data, const T& value) { Get(data) = value; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct ComponentField<std::string, void>
|
|
||||||
{
|
|
||||||
static std::string& Get(const ComponentInfo::Field_t& info, char* data) { return **reinterpret_cast<std::string**>(data); }
|
|
||||||
static void Set(const ComponentInfo::Field_t& info, char* data, const std::string& value) { Get(info, data) = value; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ComponentWrapper
|
struct ComponentWrapper
|
||||||
{
|
{
|
||||||
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
|
ComponentWrapper(const ComponentInfo& componentInfo, char* data, ::DirtyBitField* dirtyBitField)
|
||||||
: Info(componentInfo)
|
: Info(componentInfo)
|
||||||
, EntityID(*reinterpret_cast<::EntityID*>(data))
|
, EntityID(*reinterpret_cast<::EntityID*>(data))
|
||||||
, Data(data + componentInfo.GetHeaderSize())
|
, Data(data + componentInfo.GetHeaderSize())
|
||||||
|
, DirtyBitField(dirtyBitField)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
const ComponentInfo& Info;
|
const ComponentInfo& Info;
|
||||||
const ::EntityID EntityID;
|
const ::EntityID EntityID;
|
||||||
char* Data;
|
char* Data;
|
||||||
|
::DirtyBitField* DirtyBitField = nullptr;
|
||||||
|
|
||||||
ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey)
|
ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey)
|
||||||
{
|
{
|
||||||
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey);
|
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Dirty(DirtySetType type, const std::string& fieldName)
|
||||||
|
{
|
||||||
|
if (DirtyBitField == nullptr) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
auto& field = Info.Fields.at(fieldName);
|
||||||
|
return DirtyBitField->operator[](type).count(field.Index) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDirty(DirtySetType type, const std::string& fieldName, bool dirty = true)
|
||||||
|
{
|
||||||
|
if (DirtyBitField == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& field = Info.Fields.at(fieldName);
|
||||||
|
if (dirty) {
|
||||||
|
DirtyBitField->operator[](type).insert(field.Index);
|
||||||
|
} else {
|
||||||
|
DirtyBitField->operator[](type).erase(field.Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& Field(const std::string& name)
|
T& Field(const std::string& name)
|
||||||
{
|
{
|
||||||
@@ -96,32 +106,32 @@ struct ComponentWrapper
|
|||||||
{
|
{
|
||||||
friend struct ComponentWrapper;
|
friend struct ComponentWrapper;
|
||||||
private:
|
private:
|
||||||
SubscriptProxy(ComponentWrapper* component, std::string propertyName)
|
SubscriptProxy(ComponentWrapper* component, std::string fieldName)
|
||||||
: m_Component(component)
|
: m_Component(component)
|
||||||
, m_PropertyName(propertyName)
|
, m_FieldName(fieldName)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ComponentWrapper* m_Component;
|
ComponentWrapper* m_Component;
|
||||||
std::string m_PropertyName;
|
std::string m_FieldName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Return the integer value of an enum type key for this field
|
// Return the integer value of an enum type key for this field
|
||||||
ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); }
|
ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_FieldName.c_str(), enumKey); }
|
||||||
bool Dirty(DirtySet set) { return true; }
|
bool Dirty(DirtySetType type) { return m_Component->Dirty(type, m_FieldName); }
|
||||||
void SetDirty(bool dirty = true) { }
|
void SetDirty(DirtySetType type, bool dirty = true) { m_Component->SetDirty(type, m_FieldName, dirty); }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
operator T&() { return m_Component->Field<T>(m_PropertyName); }
|
operator T&() { return m_Component->Field<T>(m_FieldName); }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator=(const T val) { m_Component->SetField<T>(m_PropertyName, val); }
|
void operator=(const T val) { m_Component->SetField<T>(m_FieldName, val); }
|
||||||
// TODO: Pass by reference and rvalue (universal reference?)
|
// TODO: Pass by reference and rvalue (universal reference?)
|
||||||
//template <typename T>
|
//template <typename T>
|
||||||
//void operator=(T& val) { m_Component->SetField<T>(m_PropertyName, val); }
|
//void operator=(T& val) { m_Component->SetField<T>(m_PropertyName, val); }
|
||||||
|
|
||||||
// Specialization for string literals
|
// Specialization for string literals
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
void operator=(const char(&val)[N]) { m_Component->SetField<N>(m_PropertyName, val); }
|
void operator=(const char(&val)[N]) { m_Component->SetField<N>(m_FieldName, val); }
|
||||||
};
|
};
|
||||||
SubscriptProxy operator[](const std::string& propertyName) { return SubscriptProxy(this, propertyName); }
|
SubscriptProxy operator[](const std::string& propertyName) { return SubscriptProxy(this, propertyName); }
|
||||||
};
|
};
|
||||||
@@ -130,7 +140,7 @@ struct ComponentWrapper
|
|||||||
struct SharedComponentWrapper : ComponentWrapper
|
struct SharedComponentWrapper : ComponentWrapper
|
||||||
{
|
{
|
||||||
SharedComponentWrapper(const ComponentInfo& componentInfo, boost::shared_array<char> data)
|
SharedComponentWrapper(const ComponentInfo& componentInfo, boost::shared_array<char> data)
|
||||||
: ComponentWrapper(componentInfo, data.get())
|
: ComponentWrapper(componentInfo, data.get(), nullptr)
|
||||||
, m_DataReference(data)
|
, m_DataReference(data)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef DirtySet_h__
|
||||||
|
#define DirtySet_h__
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include "ComponentInfo.h"
|
||||||
|
|
||||||
|
enum class DirtySetType
|
||||||
|
{
|
||||||
|
Transform,
|
||||||
|
Network
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::unordered_map<DirtySetType, std::set<decltype(ComponentInfo::Field_t::Index)>> DirtyBitField;
|
||||||
|
typedef std::unordered_map<EntityID, DirtyBitField> DirtySet;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
for (auto& pair : group.PureSystems) {
|
for (auto& pair : group.PureSystems) {
|
||||||
const std::string& componentName = pair.first;
|
const std::string& componentName = pair.first;
|
||||||
auto& systems = pair.second;
|
auto& systems = pair.second;
|
||||||
const ComponentPool* pool = m_World->GetComponents(componentName);
|
ComponentPool* pool = m_World->GetComponents(componentName);
|
||||||
if (pool == nullptr) {
|
if (pool == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public:
|
|||||||
// Delete a component off an entity
|
// Delete a component off an entity
|
||||||
void DeleteComponent(EntityID entity, const std::string& componentType);
|
void DeleteComponent(EntityID entity, const std::string& componentType);
|
||||||
// Get all components of the specified type
|
// Get all components of the specified type
|
||||||
const ComponentPool* GetComponents(const std::string& componentType);
|
ComponentPool* GetComponents(const std::string& componentType);
|
||||||
// Get entity parent
|
// Get entity parent
|
||||||
EntityID GetParent(EntityID entity);
|
EntityID GetParent(EntityID entity);
|
||||||
// Change the parent of an entity
|
// Change the parent of an entity
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
#include "Core/ComponentPool.h"
|
#include "Core/ComponentPool.h"
|
||||||
|
|
||||||
|
ComponentPoolForwardIterator::ComponentPoolForwardIterator(ComponentPool* pool)
|
||||||
|
: m_ComponentPool(pool)
|
||||||
|
, m_ComponentInfo(pool->m_ComponentInfo)
|
||||||
|
, m_MemoryPoolIterator(pool->m_Pool.begin())
|
||||||
|
, m_MemoryPoolEnd(pool->m_Pool.end())
|
||||||
|
{ }
|
||||||
|
|
||||||
ComponentWrapper ComponentPoolForwardIterator::operator*() const
|
ComponentWrapper ComponentPoolForwardIterator::operator*() const
|
||||||
{
|
{
|
||||||
char* data = &(*m_MemoryPoolIterator);
|
char* data = &(*m_MemoryPoolIterator);
|
||||||
ComponentWrapper wrapper(m_ComponentInfo, data);
|
EntityID entity = *reinterpret_cast<EntityID*>(data);
|
||||||
|
ComponentWrapper wrapper(m_ComponentInfo, data, &m_ComponentPool->m_DirtySet[entity]);
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +79,7 @@ ComponentWrapper ComponentPool::Allocate(EntityID entity)
|
|||||||
memcpy(data, &entity, sizeof(EntityID));
|
memcpy(data, &entity, sizeof(EntityID));
|
||||||
|
|
||||||
m_EntityToComponent[entity] = data;
|
m_EntityToComponent[entity] = data;
|
||||||
ComponentWrapper component(m_ComponentInfo, data);
|
ComponentWrapper component(m_ComponentInfo, data, &m_DirtySet[entity]);
|
||||||
|
|
||||||
// Copy defaults
|
// Copy defaults
|
||||||
memcpy(component.Data, m_ComponentInfo.Defaults.get(), m_ComponentInfo.Stride);
|
memcpy(component.Data, m_ComponentInfo.Defaults.get(), m_ComponentInfo.Stride);
|
||||||
@@ -82,7 +90,9 @@ ComponentWrapper ComponentPool::Allocate(EntityID entity)
|
|||||||
|
|
||||||
ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
|
ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
|
||||||
{
|
{
|
||||||
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
|
auto data = m_EntityToComponent.at(ent);
|
||||||
|
auto bitField = &m_DirtySet[ent];
|
||||||
|
return ComponentWrapper(m_ComponentInfo, data, bitField);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ComponentPool::KnowsEntity(EntityID ent)
|
bool ComponentPool::KnowsEntity(EntityID ent)
|
||||||
@@ -95,16 +105,17 @@ void ComponentPool::Delete(ComponentWrapper& wrapper)
|
|||||||
ComponentWrapper::Destroy(wrapper.Info, wrapper.Data);
|
ComponentWrapper::Destroy(wrapper.Info, wrapper.Data);
|
||||||
m_EntityToComponent.erase(wrapper.EntityID);
|
m_EntityToComponent.erase(wrapper.EntityID);
|
||||||
m_Pool.Free(wrapper.Data - sizeof(EntityID));
|
m_Pool.Free(wrapper.Data - sizeof(EntityID));
|
||||||
|
m_DirtySet.erase(wrapper.EntityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentPool::iterator ComponentPool::begin() const
|
ComponentPool::iterator ComponentPool::begin()
|
||||||
{
|
{
|
||||||
return iterator(m_ComponentInfo, m_Pool.begin(), m_Pool.end());
|
return iterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentPool::iterator ComponentPool::end() const
|
ComponentPool::iterator ComponentPool::end()
|
||||||
{
|
{
|
||||||
return iterator(m_ComponentInfo, m_Pool.end(), m_Pool.end());
|
return iterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ComponentPool::size() const
|
size_t ComponentPool::size() const
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ void World::DeleteComponent(EntityID entity, const std::string& componentType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ComponentPool* World::GetComponents(const std::string& componentType)
|
ComponentPool* World::GetComponents(const std::string& componentType)
|
||||||
{
|
{
|
||||||
auto it = m_ComponentPools.find(componentType);
|
auto it = m_ComponentPools.find(componentType);
|
||||||
return (it != m_ComponentPools.end()) ? it->second : nullptr;
|
return (it != m_ComponentPools.end()) ? it->second : nullptr;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ void PlayerMovementSystem::Update(double dt)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_SprintEffectTimer = 0.f;
|
m_SprintEffectTimer = 0.f;
|
||||||
const ComponentPool* pool = m_World->GetComponents("SprintAbility");
|
auto pool = m_World->GetComponents("SprintAbility");
|
||||||
if (pool == nullptr) {
|
if (pool == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, Entity
|
|||||||
transformEntityToSpawnPoint(spawnedEntity, spawnPoint);
|
transformEntityToSpawnPoint(spawnedEntity, spawnPoint);
|
||||||
//Check if the spawned entity collides with anything, and if so, continue to the next spawnpoint.
|
//Check if the spawned entity collides with anything, and if so, continue to the next spawnpoint.
|
||||||
EntityAABB spawnedBox = *Collision::EntityAbsoluteAABB(spawnedEntity);
|
EntityAABB spawnedBox = *Collision::EntityAbsoluteAABB(spawnedEntity);
|
||||||
const ComponentPool* otherSpawnedEntities = spawnPoint.World->GetComponents(dontCollideComponent);
|
auto otherSpawnedEntities = spawnPoint.World->GetComponents(dontCollideComponent);
|
||||||
for (const auto& obj : *otherSpawnedEntities) {
|
for (const auto& obj : *otherSpawnedEntities) {
|
||||||
if (spawnedEntity.ID == obj.EntityID) {
|
if (spawnedEntity.ID == obj.EntityID) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user