Program Listing for File World.hpp

Return to documentation for file (include/ari/en/World.hpp)

#pragma once
#include "../aridef.hpp"
#include "tinystl/vector.h"
#include "EventSubscriber.hpp"
#include <algorithm>
#include <unordered_map>
#include "bx/spscqueue.h"

namespace ftl
{
    class TaskScheduler;
}

namespace ari
{
    class Node;
    class System;
    class Entity;

    class ARI_API World
    {
    public:

        enum class UpdateType
        {
            Sync,
            Async
        };

        World();

        ~World();

        void SetUpdateType(UpdateType type) { m_UpdateType = type; }

        UpdateType GetUpdateType() const { return m_UpdateType; }

        void AddSystem(System* p_system);

        void RemoveSystem(System* p_system);

        void AddEntity(Entity* p_entity);

        void RemoveEntity(Entity* p_entity);

        void Update(float tick);

        void _AddToDestroyQueue(Node* node);

        template<typename T>
        void subscribe(EventSubscriber<T>* subscriber)
        {
            auto index = getTypeIndex<T>();
            auto found = subscribers.find(index);
            if (found == subscribers.end())
            {
                tinystl::vector<Internal::BaseEventSubscriber*> subList;
                subList.push_back(subscriber);

                subscribers.insert({ index, subList });
            }
            else
            {
                found->second.push_back(subscriber);
            }
        }

        template<typename T>
        void unsubscribe(EventSubscriber<T>* subscriber)
        {
            auto index = getTypeIndex<T>();
            auto found = subscribers.find(index);
            if (found != subscribers.end())
            {
                found->second.erase(std::remove(found->second.begin(), found->second.end(), subscriber), found->second.end());
                if (found->second.size() == 0)
                {
                    subscribers.erase(found);
                }
            }
        }

        void unsubscribeAll(void* subscriber)
        {
            for (auto kv : subscribers)
            {
                kv.second.erase(std::remove(kv.second.begin(), kv.second.end(), subscriber), kv.second.end());
                if (kv.second.empty())
                {
                    subscribers.erase(subscribers.find(kv.first));
                }
            }
        }


        template<typename T>
        void emit(const T& event)
        {
            auto found = subscribers.find(getTypeIndex<T>());
            if (found != subscribers.end())
            {
                for (auto* base : found->second)
                {
                    auto* sub = reinterpret_cast<EventSubscriber<T>*>(base);
                    sub->Receive(this, event);
                }
            }
        }

        const tinystl::vector<Entity*>& GetAllEntities() const { return Entities; }

        ftl::TaskScheduler* GetTaskScheduler() const { return m_pTaskScheduler; }

    protected:

        std::unordered_map<TypeIndex,
            tinystl::vector<Internal::BaseEventSubscriber*>> subscribers;
        bx::SpScUnboundedQueueT<Node>   m_qDestroyQueue;
        tinystl::vector<System*> systems;
        tinystl::vector<Entity*> Entities;
        ftl::TaskScheduler  *   m_pTaskScheduler;
        UpdateType              m_UpdateType;

        void CheckDestroyQueue();

    }; // World

} // ari