Files
academy2/modules/world/new_world.h
2021-07-31 03:37:28 +03:00

200 lines
4.7 KiB
C++

#include <scene/3d/spatial.h>
#define MAX_ENTITIES 1000
#define MAX_COMPONENTS 16
class NewWorld: public Spatial {
GDCLASS(NewWorld, Spatial)
class EntityManager {
List<int> available_entities;
int entity_count;
uint32_t signatures[MAX_ENTITIES];
public:
EntityManager()
{
int e;
for (e = 0; e < MAX_ENTITIES; e++) {
available_entities.push_back(e);
signatures[e] = 0U;
}
entity_count = 0;
}
int create_entity()
{
int ret;
if (entity_count >= MAX_ENTITIES || available_entities.size() == 0)
return -1;
ret = available_entities.front()->get();
available_entities.pop_front();
entity_count++;
return ret;
}
void destroy_entity(int e)
{
if (e >= MAX_ENTITIES)
return;
entity_count--;
available_entities.push_back(e);
signatures[e] = 0U;
}
inline void set_signature(int e, uint32_t sig)
{
signatures[e] = sig;
}
inline uint32_t get_signature(int e)
{
return signatures[e];
}
};
class IComponentArray {
public:
virtual ~IComponentArray() = default;
virtual void destroyed(int entity) = 0;
};
template <typename T>
class ComponentArray: public IComponentArray {
Vector<T> component_array;
HashMap<int, size_t> entity_to_index;
HashMap<size_t, int> index_to_entity;
size_t size;
public:
void insert_data(int entity, T component)
{
if (entity_to_index.has(entity))
return;
size_t new_index = size;
entity_to_index[entity] = new_index;
index_to_entity[new_index] = entity;
component_array[new_index] = component;
size++;
}
void remove_data(int entity)
{
if (!entity_to_index.has(entity))
return;
size_t removed_index = entity_to_index[entity];
size_t last_index = size - 1;
component_array[removed_index] = component_array[last_index];
int last_entity = index_to_entity[last_index];
entity_to_index[last_entity] = removed_index;
index_to_entity[removed_index] = last_entity;
entity_to_index.erase(entity);
index_to_entity.erase(last_index);
size--;
}
T *get(int entity)
{
if (!entity_to_index.has(entity)) {
return NULL;
}
return &component_array[entity_to_index[entity]];
}
void destroyed(int entity) override
{
remove_data(entity);
}
};
#define __REFLECT_NAME(N) #N
class ComponentManager {
HashMap<const char *, int> component_types{};
HashMap<const char *, IComponentArray *> component_arrays{};
int next_component_type{};
template <typename T>
ComponentArray<T> *get_component_array()
{
const char* type_name = __REFLECT_NAME(T);
if (!component_types.has(type_name))
return NULL;
return static_cast<ComponentArray<T> >(component_arrays[type_name]);
}
public:
template<typename T>
void register_component()
{
const char* type_name = __REFLECT_NAME(T);
component_types[type_name] = next_component_type;
component_arrays[type_name] = memnew(ComponentArray<T>());
next_component_type++;
}
template<typename T>
int get_component_type()
{
const char* type_name = __REFLECT_NAME(T);
return component_types[type_name] *
component_types.has(type_name) -
1 * (!component_types.has(type_name));
}
template<typename T>
void add_component(int entity, T component)
{
get_component_array<T>()->insert_data(entity, component);
}
template<typename T>
void remove_component(int entity)
{
get_component_array<T>()->remove(entity);
}
template<typename T>
T &get_component(int entity)
{
get_component_array<T>()->get_data(entity);
}
void destroyed(int entity)
{
const char * const *e = component_arrays.next(NULL);
while (e) {
component_arrays[*e]->destroyed(entity);
e = component_arrays.next(e);
}
}
};
class System {
public:
Vector<uint32_t> entities;
};
class SystemManager {
HashMap<const char *, System *> systems;
HashMap<const char *, uint32_t> signatures;
public:
template<typename T>
T *register_system()
{
const char* type_name = __REFLECT_NAME(T);
T * system = memnew(T);
systems[type_name] = system;
return system;
}
template<typename T>
void set_signature(uint32_t signature)
{
const char* type_name = __REFLECT_NAME(T);
signatures[type_name] = signature;
}
void destroyed(int entity)
{
const char * const * e = systems.next(NULL);
while (e) {
systems[*e]->entities.erase(entity);
e = systems.next(e);
}
}
void signature_changed(int entity, uint32_t signature)
{
const char * const * e = systems.next(NULL);
while (e) {
if ((signature & signatures[*e]) == signatures[*e])
systems[*e]->entities.push_back(entity);
else
systems[*e]->entities.erase(entity);
e = systems.next(e);
}
}
};
ComponentManager cman;
EntityManager eman;
SystemManager sman;
};