2022-11-30 00:46:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
2022-12-15 10:07:22 +00:00
|
|
|
#include "log.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-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)
|
2022-12-14 22:50:17 +00:00
|
|
|
{
|
2023-01-02 17:24:20 +00:00
|
|
|
return m_componentSignaturePositions.at(hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
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-12-20 23:51:04 +00:00
|
|
|
Application* app() { return m_app; }
|
|
|
|
|
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-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
|
|
|
}
|