Support tagging entities in ECS

The ECS previously wasn't capable of  adding tags to the entities; the
'C' of ECS wasn't there. The tagging still needs some tests.
This commit is contained in:
Eric-Paul Ickhorn 2024-09-12 23:27:12 +02:00
parent 81e10aa64b
commit 25399640a4
8 changed files with 163 additions and 53 deletions

View File

@ -2,6 +2,7 @@
#ifndef VOXULA_H
#define VOXULA_H
#include <stdbool.h>
#include <stdint.h>
#include <voxula/internals/utility.h>
@ -19,6 +20,11 @@ vecs_s * vecs_new();
void vecs_free(vecs_s *ecs);
vecs_entity_s vecs_summon(vecs_s *ecs);
void vecs_vanish(vecs_entity_s *entity);
void vecs_vanish(vecs_entity_s entity);
bool vecs_has(vecs_entity_s entity, const char *name);
void vecs_tag(vecs_entity_s entity, const char *name);
void * vecs_attach(vecs_entity_s entity, const char *name, uint32_t size);
void vecs_detach(vecs_entity_s entity, const char *name);
#endif // VOXULA_H

View File

@ -15,6 +15,6 @@ struct vecs_entity
};
vecs_entity_s vecs_summon(void *ecs_pointer);
void vecs_vanish(vecs_entity_s *entity);
void vecs_vanish(vecs_entity_s entity);
#endif // VECS_ENTITY_H

View File

@ -6,46 +6,16 @@
#include <voxula/internals/utility.h>
#include <voxula/internals/ecs/lookup.h>
#include <voxula/internals/ecs/tag.h>
typedef struct vecs vecs_s;
typedef struct vecs_shadow vecs_shadow_s;
typedef struct vecs_tag vecs_tag_s;
typedef struct vecs_tag_name_resolver vecs_tag_name_resolver_s;
typedef struct vecs_tag_name vecs_tag_name_s;
struct vecs_tag_name
{
vx_uuid_d uuid;
uint32_t length;
char *string;
};
struct vecs_tag_name_resolver
{
uint32_t names_capacity;
uint32_t num_names;
vecs_tag_name_s *names;
vx_uuid_table_s *uuid_table;
vx_arena_s *string_arena;
};
struct vecs_tag
{
void *pointer;
vecs_tag_s *next_in_chain;
vecs_tag_name_s *name;
vecs_tag_s *next_with_same_name;
vecs_tag_s *previous_with_same_name;
};
struct vecs_shadow
{
vx_uuid_d identifier;
vecs_tag_s *first_tag;
void *first_tag;
};
struct vecs
@ -57,13 +27,7 @@ struct vecs
vx_uuid_table_s *uuid_table;
};
vecs_s * vecs_new();
vecs_s * vecs_new(vx_uuid_table_s *uuid_table);
void vecs_free(vecs_s *ecs);
vecs_tag_name_resolver_s vecs_create_tag_name_resolver();
void vecs_delete_tag_name_resolver(vecs_tag_name_resolver_s *resolver);
vecs_tag_name_s * vecs_make_tag_name(vecs_tag_name_resolver_s *resolver, const char *name);
vecs_tag_name_s * vecs_search_tag_name(vecs_tag_name_resolver_s *resolver, const char *name);
#endif // VECS_H

View File

@ -0,0 +1,47 @@
#ifndef VOXULA_ECS_TAG_H
#define VOXULA_ECS_TAG_H
#include <stdint.h>
#include <voxula/internals/ecs/entity.h>
#include <voxula/internals/ecs/tag.h>
typedef struct vecs_tag_name_resolver vecs_tag_name_resolver_s;
typedef struct vecs_tag_name vecs_tag_name_s;
typedef struct vecs_tag vecs_tag_s;
struct vecs_tag_name
{
vx_uuid_d uuid;
uint32_t length;
char *string;
vecs_tag_s *first_user;
};
struct vecs_tag_name_resolver
{
uint32_t names_capacity;
uint32_t num_names;
vecs_tag_name_s *names;
vx_uuid_table_s *uuid_table;
vx_arena_s *string_arena;
};
struct vecs_tag
{
void *pointer;
vecs_tag_s *next_in_chain;
vecs_tag_name_s *name;
vecs_tag_s *next_with_same_name;
vecs_tag_s *previous_with_same_name;
};
vecs_tag_name_resolver_s vecs_create_tag_name_resolver(vx_uuid_table_s *uuid_table);
void vecs_delete_tag_name_resolver(vecs_tag_name_resolver_s *resolver);
vecs_tag_name_s * vecs_make_tag_name(vecs_tag_name_resolver_s *resolver, const char *name);
vecs_tag_name_s * vecs_search_tag_name(vecs_tag_name_resolver_s *resolver, const char *name);
#endif // VOXULA_ECS_TAG_H

View File

@ -16,10 +16,3 @@ vecs_entity_s vecs_summon(void *ecs_pointer)
vecs_register_entity(&ecs->lookup_map, shadow);
return entity;
}
void vecs_vanish(vecs_entity_s *entity)
{
vecs_s *ecs = entity->head_structure;
vecs_shadow_s *shadow = vecs_lookup_entity(&ecs->lookup_map, entity->uuid);
vecs_unregister_entity(&ecs->lookup_map, shadow);
}

View File

@ -1,15 +1,16 @@
#include <voxula/internals/ecs/lookup.h>
#include <voxula/internals/ecs/tag.h>
#include <voxula/internals/ecs/head.h>
#include <stdlib.h>
vecs_s * vecs_new()
vecs_s * vecs_new(vx_uuid_table_s *uuid_table)
{
vecs_s *ecs = malloc(sizeof(vecs_s));
ecs->resolver = vecs_create_tag_name_resolver();
ecs->lookup_map = vecs_create_lookup_map();
ecs->resolver = vecs_create_tag_name_resolver(uuid_table);
ecs->lookup_map = vecs_create_lookup_map(uuid_table);
ecs->shadow_pool = vx_new_pool(sizeof(vecs_shadow_s), 8192);
ecs->tag_pool = vx_new_pool(sizeof(vecs_tag_s), 32768);
ecs->uuid_table = vx_new_uuid_table();
ecs->uuid_table = uuid_table;
return ecs;
}

View File

@ -1,14 +1,16 @@
#include <voxula/internals/ecs/head.h>
#include <voxula/internals/ecs/tag.h>
#include <stdlib.h>
#include <string.h>
vecs_tag_name_resolver_s vecs_create_tag_name_resolver()
vecs_tag_name_resolver_s vecs_create_tag_name_resolver(vx_uuid_table_s *uuid_table)
{
vecs_tag_name_resolver_s resolver;
resolver.names_capacity = 1024;
resolver.num_names = 0;
resolver.names = malloc(resolver.names_capacity * sizeof(vecs_tag_name_s));
resolver.string_arena = vx_new_arena(16384);
resolver.uuid_table = uuid_table;
return resolver;
}
@ -26,6 +28,7 @@ vecs_tag_name_s * vecs_force_create_tag_name(vecs_tag_name_resolver_s *resolver,
tag_name->length = len_name;
tag_name->string = vx_arena_dupe_string(resolver->string_arena, name);
tag_name->uuid = vx_new_uuid(resolver->uuid_table);
tag_name->first_user = NULL;
return tag_name;
}

96
modules/ecs/src-c/tag.c Normal file
View File

@ -0,0 +1,96 @@
#include <voxula/internals/ecs/tag.h>
#include <voxula/internals/ecs/head.h>
#include <stdlib.h>
vecs_tag_s * vecs_find_tag_in_entity(vecs_entity_s entity, const char *name)
{
vecs_s *ecs = entity.head_structure;
vecs_shadow_s *shadow = vecs_lookup_entity(&ecs->lookup_map, entity.uuid);
if( ! shadow)
{
return NULL;
}
vecs_tag_name_s *tag_name = vecs_search_tag_name(&ecs->resolver, name);
vecs_tag_s *tag = shadow->first_tag;
while(tag != NULL)
{
if(tag->name->uuid == tag_name->uuid)
{
break;
}
tag = tag->next_in_chain;
}
return tag;
}
vecs_tag_s * vecs_make_tag_in_entity(vecs_entity_s entity, const char *name)
{
vecs_s *ecs = entity.head_structure;
vecs_shadow_s *shadow = vecs_lookup_entity(&ecs->lookup_map, entity.uuid);
vecs_tag_name_s *tag_name = vecs_make_tag_name(&ecs->resolver, name);
vecs_tag_s *tag = shadow->first_tag;
while(tag)
{
if(tag->name->uuid == tag_name->uuid)
{
break;
}
tag = tag->next_in_chain;
}
if( ! tag)
{
tag = vx_pool(ecs->tag_pool);
tag->name = tag_name;
tag->next_in_chain = shadow->first_tag;
shadow->first_tag = tag;
tag->next_with_same_name = tag_name->first_user;
tag_name->first_user = tag;
if(tag->next_with_same_name)
{
tag->next_with_same_name->previous_with_same_name = tag;
}
}
return tag;
}
bool vecs_has(vecs_entity_s entity, const char *name)
{
vecs_tag_s *tag = vecs_find_tag_in_entity(entity, name);
if(tag == NULL)
{
return false;
}
return true;
}
void vecs_tag(vecs_entity_s entity, const char *name)
{
vecs_tag_s *tag = vecs_make_tag_in_entity(entity, name);
tag->pointer = NULL;
}
void * vecs_attach(vecs_entity_s entity, const char *name, uint32_t size)
{
vecs_tag_s *tag = vecs_make_tag_in_entity(entity, name);
tag->pointer = malloc(size);
return tag->pointer;
}
void vecs_detach(vecs_entity_s entity, const char *name)
{
vecs_tag_s *tag = vecs_find_tag_in_entity(entity, name);
if( ! tag)
{
return;
}
if(tag->next_with_same_name)
{
tag->next_with_same_name->previous_with_same_name = tag->previous_with_same_name;
}
if(tag->previous_with_same_name)
{
tag->previous_with_same_name->next_with_same_name = tag->next_with_same_name;
}
vx_unpool(tag);
}