200 lines
4.7 KiB
C++
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;
|
|
};
|
|
|