Program Listing for File component_array.h

Return to documentation for file (rootex/utility/component_array.h)

#pragma once

#include "common/types.h"
#include "component_array_iterator.h"

#define MAX_COMPONENT_ARRAY_SIZE 10000

template <typename Component, class A = std::allocator<Component>>
class ComponentArray
{
private:
    Vector<Component> m_Data;
    Vector<bool> m_IsValid;
    size_t m_Curr;
    size_t m_ArraySize;

public:
    ComponentArray()
    {
        m_Data.reserve(MAX_COMPONENT_ARRAY_SIZE);
        m_IsValid.reserve(MAX_COMPONENT_ARRAY_SIZE);
        for (int i = 0; i < MAX_COMPONENT_ARRAY_SIZE; i++)
        {
            m_IsValid.push_back(true);
        }
        m_Curr = 0;
        m_ArraySize = 0;
    }

    ComponentArrayIterator<Component> begin()
    {
        int index = 0;
        while (!m_IsValid[index])
        {
            index++;
        }
        return ComponentArrayIterator<Component>(m_IsValid, m_Data.begin() + index);
    }

    ComponentArrayIterator<Component> end() { return ComponentArrayIterator<Component>(m_IsValid, m_Data.begin() + m_Curr); }

    void push_back(const Component& item)
    {
        if (m_ArraySize == MAX_COMPONENT_ARRAY_SIZE)
        {
            ERR("Component set for " + Component::s_Name + " is full. Reduce component count or increase MAX_COMPONENT_ARRAY_SIZE");
        }
        for (int i = 0; i < m_Curr; i++)
        {
            if (!m_IsValid[i])
            {
                m_Data[i] = item;
                m_IsValid[i] = true;
                m_ArraySize++;
                return;
            }
        }
        m_Data[m_Curr] = item;
        m_Curr++;
        m_ArraySize++;
    }

    void emplace_back(Entity& owner, const JSON::json& componentData)
    {
        if (m_ArraySize == MAX_COMPONENT_ARRAY_SIZE)
        {
            ERR("Component set for " + Component::s_Name + " is full. Reduce component count or increase max MAX_COMPONENT_ARRAY_SIZE");
        }

        for (int i = 0; i < m_Curr; i++)
        {
            if (!m_IsValid[i])
            {
                new (&m_Data[i]) Component(owner, componentData); //Create a new component at m_data[i]
                owner.registerComponent(&m_Data[i]);
                m_IsValid[i] = true;
                m_ArraySize++;
                return;
            }
        }
        m_Data.emplace_back(owner, componentData);
        owner.registerComponent(&m_Data[m_Curr]);
        m_Curr++;
        m_ArraySize++;
    }

    bool erase(Entity& entity)
    {
        for (int i = 0; i <= m_Curr; i++)
        {
            if (m_IsValid[i] && (m_Data[i].getOwner().getID() == entity.getID()))
            {
                m_IsValid[i] = false;
                m_Data[i].onRemove();
                m_Data[i].~Component();
                memset(&m_Data[i], 0, sizeof(m_Data[i]));
                m_ArraySize--;
                return true;
            }
        }
        return false;
    }

    Component& ComponentArray::operator[](int index)
    {
        if (index >= m_ArraySize)
        {
            ERR("Array index out of bound");
        }

        int actualIndex = 0;
        int i = 0;
        for (i = 0; i < m_Curr; i++)
        {
            if (actualIndex == index)
            {
                break;
            }
            if (m_IsValid[i])
            {
                actualIndex++;
            }
        }
        return m_Data[i];
    }

    size_t size() const { return m_ArraySize; }

    bool empty() const { return m_ArraySize == 0; }

    Component front() { return *begin(); }

    Component back() { return *end(); }
};