Initial commit
This commit is contained in:
199
modules/world/new_world.h
Normal file
199
modules/world/new_world.h
Normal file
@@ -0,0 +1,199 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user