176 lines
3.8 KiB
C++
176 lines
3.8 KiB
C++
#include "EntityManager.h"
|
|
|
|
#include <array>
|
|
|
|
#include "GlobalMemory.h"
|
|
#include "RenderDevice.h"
|
|
|
|
#include "Frame.h"
|
|
#include "TextureManager.h"
|
|
|
|
Entity& EntitySiblingIterable::Iterator::operator++()
|
|
{
|
|
current = current->nextSibling();
|
|
return *current;
|
|
}
|
|
|
|
bool EntitySiblingIterable::Iterator::operator==( Iterator const& other ) const
|
|
{
|
|
return current == other.current;
|
|
}
|
|
|
|
Entity& EntitySiblingIterable::Iterator::operator*() const
|
|
{
|
|
return *current;
|
|
}
|
|
|
|
EntitySiblingIterable::Iterator EntitySiblingIterable::begin()
|
|
{
|
|
return { current };
|
|
}
|
|
|
|
EntitySiblingIterable::Iterator EntitySiblingIterable::end()
|
|
{
|
|
return {};
|
|
}
|
|
|
|
|
|
void Entity::setParent( Entity* parent )
|
|
{
|
|
ASSERT( parent );
|
|
|
|
if ( m_parent == parent ) return;
|
|
|
|
removeParent();
|
|
|
|
// Insert self into parent.
|
|
m_parent = parent;
|
|
|
|
Entity* oldHead = parent->m_firstChild;
|
|
|
|
if ( oldHead )
|
|
{
|
|
// Old head is next after this
|
|
this->m_nextSibling = oldHead;
|
|
|
|
// This is prev to old head
|
|
oldHead->m_prevSibling = this;
|
|
}
|
|
// We are the head now.
|
|
m_parent->m_firstChild = this;
|
|
}
|
|
void Entity::addChild( Entity* child )
|
|
{
|
|
child->setParent( this );
|
|
}
|
|
|
|
void Entity::removeChild( Entity* child )
|
|
{
|
|
ASSERT( child );
|
|
child->removeParent();
|
|
}
|
|
|
|
void Entity::removeParent()
|
|
{
|
|
if ( m_parent )
|
|
{
|
|
|
|
// Replace prev of next with prev of self
|
|
if ( m_nextSibling ) m_nextSibling->m_prevSibling = m_prevSibling;
|
|
|
|
// Replace next of prev with next of self
|
|
if ( m_prevSibling )
|
|
{
|
|
m_prevSibling->m_nextSibling = m_nextSibling;
|
|
}
|
|
else
|
|
{
|
|
// We are head of chain
|
|
m_parent->m_firstChild = m_nextSibling;
|
|
}
|
|
|
|
m_nextSibling = nullptr;
|
|
m_prevSibling = nullptr;
|
|
m_parent = nullptr;
|
|
}
|
|
}
|
|
|
|
EntitySiblingIterable Entity::children() const
|
|
{
|
|
return { m_firstChild };
|
|
}
|
|
|
|
Entity::Entity( Transform const& transform )
|
|
: transform{ transform }
|
|
, model{}
|
|
, modelMesh{}
|
|
, m_parent{ nullptr }
|
|
, m_firstChild{ nullptr }
|
|
, m_prevSibling{ nullptr }
|
|
, m_nextSibling{ nullptr }
|
|
, m_flags{ 0 }
|
|
{}
|
|
|
|
Entity* EntityManager::createEntity( Transform const& transform )
|
|
{
|
|
ASSERT( count < capacity );
|
|
|
|
Entity& entity = entities[count++];
|
|
new ( &entity ) Entity{ transform };
|
|
|
|
return &entity;
|
|
}
|
|
|
|
void EntityManager::destroyEntity( Entity* entity )
|
|
{
|
|
ASSERT( entity );
|
|
|
|
VkDevice const device = pRenderDevice->device;
|
|
|
|
if ( not entity->model.isNull() )
|
|
{
|
|
for ( auto& material : entity->model.materials )
|
|
{
|
|
vkDestroySampler( device, Take( material.sampler ), nullptr );
|
|
pRenderDevice->textureManager->freeTexture( std::move( material.albedoTextureID ) );
|
|
pRenderDevice->textureManager->freeTexture( std::move( material.normalTextureID ) );
|
|
pRenderDevice->textureManager->freeTexture( std::move( material.metalRoughTextureID ) );
|
|
pRenderDevice->textureManager->freeTexture( std::move( material.emissiveTextureID ) );
|
|
}
|
|
|
|
pRenderDevice->bufferManager->freeBuffer( std::move( entity->model.vertexBuffer ) );
|
|
pRenderDevice->bufferManager->freeBuffer( std::move( entity->model.indexBuffer ) );
|
|
entity->model.primitives.clear();
|
|
entity->model.materials.clear();
|
|
}
|
|
|
|
entity->modelMesh = { 0, 0 };
|
|
}
|
|
|
|
void EntityManager::destroy()
|
|
{
|
|
Entity const* end = entities + capacity;
|
|
for ( Entity* iter = entities; iter != end; ++iter )
|
|
{
|
|
destroyEntity( iter );
|
|
}
|
|
|
|
entities = nullptr;
|
|
capacity = 0;
|
|
count = 0;
|
|
}
|
|
|
|
EntityManager::~EntityManager()
|
|
{
|
|
assert( !entities );
|
|
}
|
|
|
|
EntityManager* EntityManager_Create( GlobalMemory* mem, RenderDevice* renderDevice, uint32_t const capacity )
|
|
{
|
|
Entity* data = reinterpret_cast<Entity*>( mem->allocate( capacity * sizeof( Entity ), alignof( Entity ) ) );
|
|
memset( data, 0, capacity * sizeof( Entity ) );
|
|
|
|
std::byte* alloc = mem->allocate( sizeof( EntityManager ), alignof( EntityManager ) );
|
|
return new ( alloc ) EntityManager{ renderDevice, data, capacity };
|
|
}
|