Skip to content

Commit

Permalink
Refactored ec system a bit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chukobyte committed Feb 9, 2024
1 parent eba8041 commit b29b01f
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 38 deletions.
79 changes: 60 additions & 19 deletions seika/ecs/ec_system.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ec_system.h"

#include <string.h>

#include "seika/utils/se_string_util.h"
#include "seika/data_structures/se_queue.h"
#include "seika/memory/se_mem.h"
Expand Down Expand Up @@ -56,8 +58,27 @@ SkaECSSystem* ska_ecs_system_create(const char* systemName) {
return newSystem;
}

SkaECSSystem* ska_ecs_system_create_with_signature_string(const char* systemName, const char* signatures) {
SkaECSSystem* newSystem = ska_ecs_system_create(systemName);
SkaECSSystem* ska_ecs_system_create_from_template(SkaECSSystemTemplate* systemTemplate) {
SkaECSSystem* newSystem = SE_MEM_ALLOCATE(SkaECSSystem);
newSystem->name = se_strdup(systemTemplate->name);
newSystem->on_ec_system_register = systemTemplate->on_ec_system_register;
newSystem->on_ec_system_destroy = systemTemplate->on_ec_system_destroy;
newSystem->on_entity_registered_func = systemTemplate->on_entity_registered_func;
newSystem->on_entity_start_func = systemTemplate->on_entity_start_func;
newSystem->on_entity_end_func = systemTemplate->on_entity_end_func;
newSystem->on_entity_unregistered_func = systemTemplate->on_entity_unregistered_func;
newSystem->on_entity_entered_scene_func = systemTemplate->on_entity_entered_scene_func;
newSystem->render_func = systemTemplate->render_func;
newSystem->pre_update_all_func = systemTemplate->pre_update_all_func;
newSystem->post_update_all_func = systemTemplate->post_update_all_func;
newSystem->update_func = systemTemplate->update_func;
newSystem->fixed_update_func = systemTemplate->fixed_update_func;
newSystem->network_callback_func = systemTemplate->network_callback_func;
newSystem->on_entity_start_func = systemTemplate->on_entity_start_func;
return newSystem;
}

static SkaECSSystem* update_system_with_type_signature_string(SkaECSSystem* system, const char* signatures) {
// Take signature string, create flags, and add to system's component signature
static char typeNameBuffer[256];
char* word = typeNameBuffer;
Expand All @@ -68,7 +89,7 @@ SkaECSSystem* ska_ecs_system_create_with_signature_string(const char* systemName
*word = '\0';
const SkaComponentTypeInfo* typeInfo = ska_ecs_component_find_type_info(typeNameBuffer);
SE_ASSERT_FMT(typeInfo, "Unable to get type info for '%s'", typeNameBuffer);
newSystem->component_signature |= typeInfo->type;
system->component_signature |= typeInfo->type;
word = start;
continue;
} else if (*src == ' ') {
Expand All @@ -79,14 +100,25 @@ SkaECSSystem* ska_ecs_system_create_with_signature_string(const char* systemName

const SkaComponentTypeInfo* typeInfo = ska_ecs_component_find_type_info(typeNameBuffer);
SE_ASSERT_FMT(typeInfo, "Unable to get type info for '%s'", typeNameBuffer);
newSystem->component_signature |= typeInfo->type;
system->component_signature |= typeInfo->type;
return system;
}

SkaECSSystem* ska_ecs_system_create_with_signature_string(const char* systemName, const char* signatures) {
SkaECSSystem* newSystem = ska_ecs_system_create(systemName);
update_system_with_type_signature_string(newSystem, signatures);
return newSystem;
}

SkaECSSystem* ska_ecs_system_create_from_template_with_signature_string(SkaECSSystemTemplate* systemTemplate, const char* signatures) {
SkaECSSystem* newSystem = ska_ecs_system_create_from_template(systemTemplate);
update_system_with_type_signature_string(newSystem, signatures);
return newSystem;
}

void ska_ecs_system_destroy(SkaECSSystem* entitySystem) {
if (entitySystem->on_ec_system_destroy) {
entitySystem->on_ec_system_destroy();
entitySystem->on_ec_system_destroy(entitySystem);
}
SE_MEM_FREE(entitySystem);
}
Expand Down Expand Up @@ -137,8 +169,9 @@ void ska_ecs_system_update_entity_signature_with_systems(SkaEntity entity) {
void ska_ecs_system_event_entity_start(SkaEntity entity) {
const SkaComponentType entityComponentSignature = ska_ecs_component_manager_get_component_signature(entity);
for (size_t i = 0; i < entitySystemData.on_entity_start_systems_count; i++) {
if (SKA_FLAG_CONTAINS(entityComponentSignature, entitySystemData.on_entity_start_systems[i]->component_signature)) {
entitySystemData.on_entity_start_systems[i]->on_entity_start_func(entity);
SkaECSSystem* ecsSystem = entitySystemData.on_entity_start_systems[i];
if (SKA_FLAG_CONTAINS(entityComponentSignature, ecsSystem->component_signature)) {
ecsSystem->on_entity_start_func(ecsSystem, entity);
}
}
}
Expand All @@ -148,8 +181,9 @@ void ska_ecs_system_event_entity_end(SkaEntity entity) {
// TODO: Consider hooks for components instead of direct node component references
const SkaComponentType entityComponentSignature = ska_ecs_component_manager_get_component_signature(entity);
for (size_t i = 0; i < entitySystemData.on_entity_end_systems_count; i++) {
if (SKA_FLAG_CONTAINS(entityComponentSignature, entitySystemData.on_entity_end_systems[i]->component_signature)) {
entitySystemData.on_entity_end_systems[i]->on_entity_end_func(entity);
SkaECSSystem* ecsSystem = entitySystemData.on_entity_end_systems[i];
if (SKA_FLAG_CONTAINS(entityComponentSignature, ecsSystem->component_signature)) {
ecsSystem->on_entity_end_func(ecsSystem, entity);
}
}
// NodeComponent* nodeComponent = (NodeComponent*)ska_ecs_component_manager_get_component_unchecked(entity, CreComponentDataIndex_NODE);
Expand All @@ -171,45 +205,52 @@ void ska_ecs_system_event_entity_entered_scene(SkaEntity entity) {
// }
const SkaComponentType entityComponentSignature = ska_ecs_component_manager_get_component_signature(entity);
for (size_t i = 0; i < entitySystemData.on_entity_entered_scene_systems_count; i++) {
if (SKA_FLAG_CONTAINS(entityComponentSignature, entitySystemData.on_entity_entered_scene_systems[i]->component_signature)) {
entitySystemData.on_entity_entered_scene_systems[i]->on_entity_entered_scene_func(entity);
SkaECSSystem* ecsSystem = entitySystemData.on_entity_entered_scene_systems[i];
if (SKA_FLAG_CONTAINS(entityComponentSignature, ecsSystem->component_signature)) {
ecsSystem->on_entity_entered_scene_func(ecsSystem, entity);
}
}
}

void ska_ecs_system_event_render_systems() {
for (size_t i = 0; i < entitySystemData.render_systems_count; i++) {
entitySystemData.render_systems[i]->render_func();
SkaECSSystem* ecsSystem = entitySystemData.render_systems[i];
ecsSystem->render_func(ecsSystem);
}
}

void ska_ecs_system_event_pre_update_all_systems() {
for (size_t i = 0; i < entitySystemData.pre_update_all_systems_count; i++) {
entitySystemData.pre_update_all_systems[i]->pre_update_all_func();
SkaECSSystem* ecsSystem = entitySystemData.pre_update_all_systems[i];
ecsSystem->pre_update_all_func(ecsSystem);
}
}

void ska_ecs_system_event_post_update_all_systems() {
for (size_t i = 0; i < entitySystemData.post_update_all_systems_count; i++) {
entitySystemData.post_update_all_systems[i]->post_update_all_func();
SkaECSSystem* ecsSystem = entitySystemData.post_update_all_systems[i];
ecsSystem->post_update_all_func(ecsSystem);
}
}

void ska_ecs_system_event_update_systems(float deltaTime) {
for (size_t i = 0; i < entitySystemData.update_systems_count; i++) {
entitySystemData.update_systems[i]->update_func(deltaTime);
SkaECSSystem* ecsSystem = entitySystemData.update_systems[i];
ecsSystem->update_func(ecsSystem, deltaTime);
}
}

void ska_ecs_system_event_fixed_update_systems(float deltaTime) {
for (size_t i = 0; i < entitySystemData.fixed_update_systems_count; i++) {
entitySystemData.fixed_update_systems[i]->fixed_update_func(deltaTime);
SkaECSSystem* ecsSystem = entitySystemData.fixed_update_systems[i];
ecsSystem->fixed_update_func(ecsSystem, deltaTime);
}
}

void ska_ecs_system_event_network_callback(const char* message) {
for (size_t i = 0; i < entitySystemData.network_callback_systems_count; i++) {
entitySystemData.network_callback_systems[i]->network_callback_func(message);
SkaECSSystem* ecsSystem = entitySystemData.network_callback_systems[i];
ecsSystem->network_callback_func(ecsSystem, message);
}
}

Expand All @@ -227,7 +268,7 @@ void ska_ecs_system_insert_entity_into_system(SkaEntity entity, SkaECSSystem* sy
if (!ska_ecs_system_has_entity(entity, system)) {
system->entities[system->entity_count++] = entity;
if (system->on_entity_registered_func != NULL) {
system->on_entity_registered_func(entity);
system->on_entity_registered_func(system, entity);
}
} else {
se_logger_warn("Entity '%d' already in system '%s'", entity, system->name);
Expand All @@ -242,7 +283,7 @@ void ska_ecs_system_remove_entity_from_system(SkaEntity entity, SkaECSSystem* sy
system->entities[i] = SKA_NULL_ENTITY;
}
if (system->on_entity_unregistered_func != NULL) {
system->on_entity_unregistered_func(entity);
system->on_entity_unregistered_func(system, entity);
}

// Condense array
Expand Down
76 changes: 60 additions & 16 deletions seika/ecs/ec_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@

#include "component.h"

#define SKA_ECS_SYSTEM_CREATE(Name, ...) \
ska_ecs_system_create_with_signature_string(Name, #__VA_ARGS__)

typedef void (*OnEntityRegisteredFunc) (SkaEntity); // init
typedef void (*OnEntityStartFunc) (SkaEntity); // Useful for after initialization functionality (such as entering a scene)
typedef void (*OnEntityEndFunc) (SkaEntity); // Useful for before deletion functionality (such as leaving a scene)
typedef void (*OnEntityUnRegisteredFunc) (SkaEntity); // delete
typedef void (*OnEntityEnteredSceneFunc) (SkaEntity); // When entity enters a scene (after _start() is called)
typedef void (*RenderFunc) ();
typedef void (*PreProcessAllFunc) ();
typedef void (*PostProcessAllFunc) ();
typedef void (*UpdateFunc) (float);
typedef void (*FixedUpdateFunc) (float);
typedef void (*NetworkCallbackFunc) (const char*);
typedef void (*OnECSystemDestroy) ();
#define SKA_ECS_SYSTEM_CREATE(NAME, ...) \
ska_ecs_system_create_with_signature_string(NAME, #__VA_ARGS__)

#define SKA_ECS_SYSTEM_CREATE_FROM_TEMPLATE(TEMPLATE, ...) \
ska_ecs_system_create_from_template_with_signature_string(TEMPLATE, #__VA_ARGS__)

struct SkaECSSystem;

typedef void (*OnECSystemRegister) (struct SkaECSSystem*);
typedef void (*OnECSystemDestroy) (struct SkaECSSystem*);
typedef void (*OnEntityRegisteredFunc) (struct SkaECSSystem*, SkaEntity); // init
typedef void (*OnEntityStartFunc) (struct SkaECSSystem*, SkaEntity); // Useful for after initialization functionality (such as entering a scene)
typedef void (*OnEntityEndFunc) (struct SkaECSSystem*, SkaEntity); // Useful for before deletion functionality (such as leaving a scene)
typedef void (*OnEntityUnRegisteredFunc) (struct SkaECSSystem*, SkaEntity); // delete
typedef void (*OnEntityEnteredSceneFunc) (struct SkaECSSystem*, SkaEntity); // When entity enters a scene (after _start() is called)
typedef void (*RenderFunc) (struct SkaECSSystem*);
typedef void (*PreProcessAllFunc) (struct SkaECSSystem*);
typedef void (*PostProcessAllFunc) (struct SkaECSSystem*);
typedef void (*UpdateFunc) (struct SkaECSSystem*, float);
typedef void (*FixedUpdateFunc) (struct SkaECSSystem*, float);
typedef void (*NetworkCallbackFunc) (struct SkaECSSystem*, const char*);

typedef struct SkaECSSystem {
char* name;
// Event callbacks
OnECSystemRegister on_ec_system_register; // happens on register
OnECSystemDestroy on_ec_system_destroy;
OnEntityRegisteredFunc on_entity_registered_func;
OnEntityStartFunc on_entity_start_func;
OnEntityEndFunc on_entity_end_func;
Expand All @@ -32,17 +40,53 @@ typedef struct SkaECSSystem {
UpdateFunc update_func;
FixedUpdateFunc fixed_update_func;
NetworkCallbackFunc network_callback_func;
OnECSystemDestroy on_ec_system_destroy;
SkaComponentType component_signature;
size_t entity_count;
// Keeps track of entities that match a component signature
SkaEntity entities[SKA_MAX_ENTITIES];
} SkaECSSystem;

typedef struct SkaECSSystemTemplate {
const char* name;
OnECSystemRegister on_ec_system_register;
OnECSystemDestroy on_ec_system_destroy;
OnEntityRegisteredFunc on_entity_registered_func;
OnEntityStartFunc on_entity_start_func;
OnEntityEndFunc on_entity_end_func;
OnEntityUnRegisteredFunc on_entity_unregistered_func;
OnEntityEnteredSceneFunc on_entity_entered_scene_func;
RenderFunc render_func;
PreProcessAllFunc pre_update_all_func;
PostProcessAllFunc post_update_all_func;
UpdateFunc update_func;
FixedUpdateFunc fixed_update_func;
NetworkCallbackFunc network_callback_func;
} SkaECSSystemTemplate;

// example system template
#define SKA_ECS_SYSTEM_TEMPLATE_STRUCT SKA_STRUCT_LITERAL(SkaECSSystemTemplate){ \
.name = "example template system", \
.on_ec_system_register = NULL, \
.on_ec_system_destroy = NULL, \
.on_entity_registered_func = NULL, \
.on_entity_start_func = NULL, \
.on_entity_end_func = NULL, \
.on_entity_unregistered_func = NULL, \
.on_entity_entered_scene_func = NULL, \
.render_func = NULL, \
.pre_update_all_func = NULL, \
.post_update_all_func = NULL, \
.update_func = NULL, \
.fixed_update_func = NULL, \
.network_callback_func = NULL \
}

void ska_ecs_system_initialize();
void ska_ecs_system_finalize();
SkaECSSystem* ska_ecs_system_create(const char* systemName);
SkaECSSystem* ska_ecs_system_create_from_template(SkaECSSystemTemplate* systemTemplate);
SkaECSSystem* ska_ecs_system_create_with_signature_string(const char* systemName, const char* signatures);
SkaECSSystem* ska_ecs_system_create_from_template_with_signature_string(SkaECSSystemTemplate* systemTemplate, const char* signatures);
void ska_ecs_system_destroy(SkaECSSystem* entitySystem);
void ska_ecs_system_register(SkaECSSystem* system);
void ska_ecs_system_update_entity_signature_with_systems(SkaEntity entity);
Expand Down
23 changes: 20 additions & 3 deletions test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ typedef struct TestTransformComponent {
// test ecs callbacks

static int entityRegisteredInTestCount = 0;
void test_ecs_callback_on_entity_registered(SkaEntity entity){
void test_ecs_callback_on_entity_registered(SkaECSSystem* system, SkaEntity entity){
entityRegisteredInTestCount++;
}

Expand Down Expand Up @@ -450,9 +450,26 @@ void seika_ecs_test(void) {
testValueEcsSystem->on_entity_registered_func = test_ecs_callback_on_entity_registered;
ska_ecs_system_register(testValueEcsSystem);

SkaECSSystem* testValueTransformEcsSystem = SKA_ECS_SYSTEM_CREATE("test value transform system", TestValueComponent, TestTransformComponent);
testValueTransformEcsSystem->on_entity_registered_func = test_ecs_callback_on_entity_registered;
// Test creating with template
#define VALUE_TRANSFORM_SYSTEM_TEMPLATE &(SkaECSSystemTemplate){ \
.name = "test value transform system", \
.on_ec_system_register = NULL, \
.on_ec_system_destroy = NULL, \
.on_entity_registered_func = test_ecs_callback_on_entity_registered, \
.on_entity_start_func = NULL, \
.on_entity_end_func = NULL, \
.on_entity_unregistered_func = NULL, \
.on_entity_entered_scene_func = NULL, \
.render_func = NULL, \
.pre_update_all_func = NULL, \
.post_update_all_func = NULL, \
.update_func = NULL, \
.fixed_update_func = NULL, \
.network_callback_func = NULL \
}
SkaECSSystem* testValueTransformEcsSystem = SKA_ECS_SYSTEM_CREATE_FROM_TEMPLATE(VALUE_TRANSFORM_SYSTEM_TEMPLATE, TestValueComponent, TestTransformComponent);
ska_ecs_system_register(testValueTransformEcsSystem);
#undef VALUE_TRANSFORM_SYSTEM_TEMPLATE

// Test entity id enqueue and dequeue
#define TEST_ENTITY_QUEUE_AMOUNT 1000
Expand Down

0 comments on commit b29b01f

Please sign in to comment.