engine/include/scene.hpp

177 lines
4.7 KiB
C++
Raw Normal View History

2022-11-30 00:46:03 +00:00
#pragma once
2022-12-15 10:07:22 +00:00
#include "log.hpp"
2023-01-05 13:21:33 +00:00
#include "resource_manager.hpp"
2023-01-02 17:24:20 +00:00
#include "ecs_system.hpp"
#include <map>
2022-12-14 22:50:17 +00:00
#include <cstdint>
2023-01-02 17:24:20 +00:00
#include <typeinfo>
#include <assert.h>
2022-11-30 00:46:03 +00:00
namespace engine {
2022-12-20 23:51:04 +00:00
class Application;
2022-12-14 22:50:17 +00:00
class Scene {
2022-11-30 00:46:03 +00:00
public:
2022-12-20 23:51:04 +00:00
Scene(Application* app);
2022-11-30 00:46:03 +00:00
Scene(const Scene&) = delete;
Scene& operator=(const Scene&) = delete;
2022-11-30 10:36:50 +00:00
~Scene();
2022-11-30 00:46:03 +00:00
2022-12-15 10:07:22 +00:00
void update(float ts);
2023-01-05 13:21:33 +00:00
Application* app() { return m_app; }
/* resource stuff */
template <typename T>
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<ResourceManager<T>>());
}
template <typename T>
std::shared_ptr<T> addResource(const std::string& name, std::unique_ptr<T>&& resource)
{
auto resourceManager = getResourceManager<T>();
return resourceManager->add(name, std::move(resource));
}
template <typename T>
std::shared_ptr<T> getResource(const std::string& name)
{
auto resourceManager = getResourceManager<T>();
return resourceManager->get(name);
}
/* ecs stuff */
2023-01-02 17:24:20 +00:00
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);
2023-01-02 17:24:20 +00:00
template <typename T>
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<ComponentArray<T>>());
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 <typename T>
T* getComponent(uint32_t entity)
{
auto array = getComponentArray<T>();
return array->getData(entity);
}
template <typename T>
T* addComponent(uint32_t entity)
{
size_t hash = typeid(T).hash_code();
auto array = getComponentArray<T>();
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 <typename T>
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<T>(this));
}
template <typename T>
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<T*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
2022-12-14 22:50:17 +00:00
}
2022-11-30 00:46:03 +00:00
private:
2022-12-20 23:51:04 +00:00
Application* const m_app;
2022-12-14 22:50:17 +00:00
uint32_t m_nextEntityID = 1000;
2022-11-30 00:46:03 +00:00
2023-01-05 13:21:33 +00:00
/* resource stuff */
std::map<size_t, std::unique_ptr<IResourceManager>> m_resourceManagers{};
template <typename T>
ResourceManager<T>* 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<ResourceManager<T>*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
}
/* ecs stuff */
2023-01-02 17:24:20 +00:00
size_t m_nextSignaturePosition = 0;
// maps component hashes to signature positions
std::map<size_t, size_t> m_componentSignaturePositions{};
// maps entity ids to their signatures
std::map<uint32_t, std::bitset<MAX_COMPONENTS>> m_signatures{};
// maps component hashes to their arrays
std::map<size_t, std::unique_ptr<IComponentArray>> m_componentArrays{};
// maps system hashes to their class instantiations
std::map<size_t, std::unique_ptr<System>> m_systems{};
template <typename T>
ComponentArray<T>* 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<ComponentArray<T>*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
}
2022-11-30 00:46:03 +00:00
};
2022-12-14 22:50:17 +00:00
}