Blaze/Blaze/EntityManager.cpp

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 };
}