#pragma once #include "log.hpp" #include "resource_manager.hpp" #include "ecs_system.hpp" #include #include #include #include namespace engine { class Application; class Scene { public: Scene(Application* app); Scene(const Scene&) = delete; Scene& operator=(const Scene&) = delete; ~Scene(); void update(float ts); Application* app() { return m_app; } /* resource stuff */ template void registerResourceManager() { size_t hash = typeid(T).hash_code(); assert(m_resourceManagers.contains(hash) == false && "Registering resource manager type more than once."); m_resourceManagers.emplace(hash, std::make_unique>()); } template std::shared_ptr addResource(const std::string& name, std::unique_ptr&& resource) { auto resourceManager = getResourceManager(); return resourceManager->add(name, std::move(resource)); } template std::shared_ptr getResource(const std::string& name) { auto resourceManager = getResourceManager(); return resourceManager->get(name); } /* ecs stuff */ uint32_t createEntity(const std::string& tag, uint32_t parent = 0); uint32_t getEntity(const std::string& tag, uint32_t parent = 0); size_t getComponentSignaturePosition(size_t hash) { return m_componentSignaturePositions.at(hash); } template void registerComponent() { size_t hash = typeid(T).hash_code(); assert(m_componentArrays.contains(hash) == false && "Registering component type more than once."); m_componentArrays.emplace(hash, std::make_unique>()); size_t componentSignaturePosition = m_nextSignaturePosition++; assert(componentSignaturePosition < MAX_COMPONENTS && "Registering too many components!"); assert(m_componentSignaturePositions.contains(hash) == false); m_componentSignaturePositions.emplace(hash, componentSignaturePosition); } template T* getComponent(uint32_t entity) { auto array = getComponentArray(); return array->getData(entity); } template T* addComponent(uint32_t entity) { size_t hash = typeid(T).hash_code(); auto array = getComponentArray(); array->insertData(entity, T{}); // set the component bit for this entity size_t componentSignaturePosition = m_componentSignaturePositions.at(hash); auto& signatureRef = m_signatures.at(entity); signatureRef.set(componentSignaturePosition); for (auto& [systemName, system] : m_systems) { if ((system->m_signature & signatureRef) == system->m_signature) { system->m_entities.insert(entity); } } return array->getData(entity); } template void registerSystem() { size_t hash = typeid(T).hash_code(); assert(m_systems.find(hash) == m_systems.end() && "Registering system more than once."); m_systems.emplace(hash, std::make_unique(this)); } template T* getSystem() { size_t hash = typeid(T).hash_code(); auto it = m_systems.find(hash); if (it == m_systems.end()) { throw std::runtime_error("Cannot find ecs system."); } auto ptr = it->second.get(); auto castedPtr = dynamic_cast(ptr); assert(castedPtr != nullptr); return castedPtr; } private: Application* const m_app; uint32_t m_nextEntityID = 1000; /* resource stuff */ std::map> m_resourceManagers{}; template ResourceManager* getResourceManager() { size_t hash = typeid(T).hash_code(); auto it = m_resourceManagers.find(hash); if (it == m_resourceManagers.end()) { throw std::runtime_error("Cannot find resource manager."); } auto ptr = it->second.get(); auto castedPtr = dynamic_cast*>(ptr); assert(castedPtr != nullptr); return castedPtr; } /* ecs stuff */ size_t m_nextSignaturePosition = 0; // maps component hashes to signature positions std::map m_componentSignaturePositions{}; // maps entity ids to their signatures std::map> m_signatures{}; // maps component hashes to their arrays std::map> m_componentArrays{}; // maps system hashes to their class instantiations std::map> m_systems{}; template ComponentArray* getComponentArray() { size_t hash = typeid(T).hash_code(); auto it = m_componentArrays.find(hash); if (it == m_componentArrays.end()) { throw std::runtime_error("Cannot find component array."); } auto ptr = it->second.get(); auto castedPtr = dynamic_cast*>(ptr); assert(castedPtr != nullptr); return castedPtr; } }; }