Added but didn't test state-struct and entity lookup, entity tagging and entity registry functionality
This commit is contained in:
parent
3f7da48836
commit
6979728a96
|
@ -57,10 +57,10 @@ function compile_module_c_sources {
|
|||
MODULE_NAME=$1
|
||||
|
||||
get_include_path_configuration $MODULE_NAME
|
||||
echo $INCLUDE_STATEMENTS
|
||||
|
||||
MODULE_SOURCE_PATH="$REPOSITORY_FOLDER/$MODULE_NAME/src-c/"
|
||||
MODULE_OBJECTS_FOLDER="$MAIN_OBJECTS_FOLDER/$MODULE_NAME/"
|
||||
rm -r $MODULE_OBJECTS_FOLDER
|
||||
mkdir -p $MODULE_OBJECTS_FOLDER
|
||||
|
||||
# Loop through all files in the 'src-c'-folder and hand them over to GCC
|
||||
|
|
|
@ -6,59 +6,53 @@
|
|||
#include <librr/types.h>
|
||||
#include <librr/linear_algebra.h>
|
||||
|
||||
typedef void * MtType;
|
||||
typedef void * MtEntity;
|
||||
|
||||
/// @brief: An MtTask is a piece of functionality with an own state/context which will be executed on the same thread or set of threads.
|
||||
typedef void * MtTask;
|
||||
typedef void * MtState;
|
||||
|
||||
|
||||
|
||||
typedef void (*mt_type_effector_fn) (MtType type, void *userdata, usz_t invocation);
|
||||
typedef void (*mt_entity_effector_fn) (MtEntity entity, void *userdata, usz_t invocation);
|
||||
typedef void (*mt_task_main_fn) (MtTask task, void *userdata);
|
||||
typedef void (*MtEffectorFn) (MtEntity entity, void *userdata, usz_t invocation_id);
|
||||
typedef void (*MtTaskMainFn) (MtTask task, void *userdata);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *task_name;
|
||||
usz_t min_num_threads;
|
||||
usz_t max_num_threads;
|
||||
MtTaskMainFn continuous_threads[4];
|
||||
void *userdata;
|
||||
|
||||
} MtTaskCreationInfo;
|
||||
|
||||
|
||||
|
||||
MtState mt_create_state(char *app_name);
|
||||
MtState mt_initialize(char *app_name);
|
||||
void mt_cleanup(MtState state);
|
||||
void mt_start(MtState state);
|
||||
|
||||
MtType mt_register_type(char *identifier);
|
||||
void mt_forget_type(MtType type);
|
||||
MtEntity mt_summon(MtState state);
|
||||
|
||||
MtEntity mt_make(MtType type);
|
||||
void mt_add_registration_effector(MtState state, char *effector_name, mt_type_effector_fn function, void *userdata);
|
||||
void mt_add_create_effector(MtType type, char *effector_name, mt_entity_effector_fn function, void *userdata);
|
||||
void mt_add_delete_effector(MtType type, char *effector_name, mt_entity_effector_fn function, void *userdata);
|
||||
void mt_add_entity_tick_effector(MtType type, char *effector_name, usz_t ticks_delta, mt_entity_effector_fn function, void *userdata);
|
||||
void mt_add_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, mt_entity_effector_fn function, void *userdata);
|
||||
void mt_add_create_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata);
|
||||
void mt_add_delete_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata);
|
||||
void mt_add_entity_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata);
|
||||
void mt_add_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata);
|
||||
void mt_remove_effector(MtState state, const char *effector_name);
|
||||
|
||||
/// @brief Adds a tick effector which only acts upon entitys with certain tags.
|
||||
/// @param type The type for which to add the tick effector.
|
||||
/// @param state The state in which the tick effector should reside.
|
||||
/// @param effector_name The name of the effector. This will be copied into the effector's structure.
|
||||
/// @param ticks_delta The wanted number of ticks between two invocations of the effector
|
||||
/// @param ticks_delta The wanted number of ticks between two invocations of the effector.
|
||||
/// @param function The function to call for an entity if it contains all necessary tags.
|
||||
/// @param tag_names A nullpointer-terminated list of tag-ids that must be present in an entity for that entity to be effected.
|
||||
void mt_add_tagged_tick_effector(MtType type, char *effector_name, usz_t ticks_delta, mt_entity_effector_fn function, char **tag_names);
|
||||
void mt_add_tagged_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, char **tag_names);
|
||||
|
||||
void mt_tag_i64(MtEntity entity, char *name, i64_t integer);
|
||||
void mt_tag_f64(MtEntity entity, char *name, f64_t real);
|
||||
void mt_tag_str(MtEntity entity, char *name, char *string);
|
||||
void mt_tag_ptr(MtEntity entity, char *name, void *pointer);
|
||||
void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector);
|
||||
void mt_tag_vec3(MtEntity entity, char *name, rr_vec2f_s vector);
|
||||
void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector);
|
||||
void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector);
|
||||
|
||||
void mt_untag(MtEntity entity, char *name);
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
|
||||
#ifndef MT_ENTITY_POOL_H
|
||||
#define MT_ENTITY_POOL_H
|
||||
|
||||
#include <librr/types.h>
|
||||
#include <librr/linear_algebra.h>
|
||||
|
||||
typedef struct MtEntityLookupTree MtEntityLookupTree;
|
||||
typedef struct MtEntityListL1 MtEntityListL1;
|
||||
typedef struct MtEntityListL2 MtEntityListL2;
|
||||
typedef struct MtEntityListL3 MtEntityListL3;
|
||||
typedef struct MtEntityPool MtEntityPool;
|
||||
typedef struct MtEntityRegistry MtEntityRegistry;
|
||||
typedef struct MtEntity * MtEntity;
|
||||
typedef struct MtTag * MtTag;
|
||||
|
||||
struct MtEntityPool
|
||||
{
|
||||
usz_t capacity;
|
||||
struct MtEntity *entities;
|
||||
struct MtEntity *first_free;
|
||||
MtEntityPool *continuation;
|
||||
};
|
||||
|
||||
struct MtEntityLookupTree
|
||||
{
|
||||
MtEntityListL1 *sublists[256];
|
||||
};
|
||||
|
||||
struct MtEntityListL1
|
||||
{
|
||||
MtEntityListL2 *sublists[256];
|
||||
};
|
||||
|
||||
struct MtEntityListL2
|
||||
{
|
||||
MtEntityListL3 *sublists[256];
|
||||
};
|
||||
|
||||
struct MtEntityListL3
|
||||
{
|
||||
struct MtEntity *entities[256];
|
||||
};
|
||||
|
||||
struct MtEntityRegistry
|
||||
{
|
||||
MtEntityPool pool;
|
||||
MtEntityLookupTree lookup;
|
||||
};
|
||||
|
||||
struct MtEntity
|
||||
{
|
||||
void *parent_state;
|
||||
MtEntity pool_next_free;
|
||||
|
||||
u32_t identifier;
|
||||
u16_t tags_capacity;
|
||||
u16_t num_tags;
|
||||
struct MtTag *tags;
|
||||
};
|
||||
|
||||
struct MtTag
|
||||
{
|
||||
u32_t identifier;
|
||||
union MtTagData
|
||||
{
|
||||
i64_t integer;
|
||||
f64_t real;
|
||||
char *string;
|
||||
void *pointer;
|
||||
rr_vec2f_s vec2f;
|
||||
rr_vec3f_s vec3f;
|
||||
rr_vec4f_s vec4f;
|
||||
} data;
|
||||
};
|
||||
|
||||
MtEntityRegistry mt_create_entity_registry();
|
||||
void mt_delete_entity_registry(MtEntityRegistry *entity_list);
|
||||
|
||||
MtEntity mt_create_entity(void *state_voidptr, u32_t identifier);
|
||||
MtEntity mt_get_entity(void *state_voidptr, u32_t identifier);
|
||||
|
||||
void mt_tag_i64(MtEntity entity, char *name, i64_t integer);
|
||||
void mt_tag_f64(MtEntity entity, char *name, f64_t real);
|
||||
void mt_tag_str(MtEntity entity, char *name, char *string);
|
||||
void mt_tag_ptr(MtEntity entity, char *name, void *pointer);
|
||||
void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector);
|
||||
void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector);
|
||||
void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector);
|
||||
|
||||
void mt_untag(MtEntity entity, char *name);
|
||||
|
||||
i64_t mt_get_i64_tag(MtEntity entity, char *name);
|
||||
f64_t mt_get_f64_tag(MtEntity entity, char *name);
|
||||
char * mt_get_str_tag(MtEntity entity, char *name);
|
||||
void * mt_get_ptr_tag(MtEntity entity, char *name);
|
||||
rr_vec2f_s mt_get_vec2_tag(MtEntity entity, char *name);
|
||||
rr_vec3f_s mt_get_vec3_tag(MtEntity entity, char *name);
|
||||
rr_vec4f_s mt_get_vec4_tag(MtEntity entity, char *name);
|
||||
|
||||
|
||||
|
||||
MtEntityPool mt_create_entity_pool(usz_t capacity);
|
||||
void mt_delete_entity_pool(MtEntityPool *pool);
|
||||
|
||||
MtEntity mt_get_entity_pool_slot(MtEntityPool *pool);
|
||||
|
||||
|
||||
#endif // MT_ENTITY_POOL_H
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#ifndef MT_STATE_H
|
||||
#define MT_STATE_H
|
||||
|
||||
#include <tag_registry.h>
|
||||
#include <entity.h>
|
||||
|
||||
#include <librr/types.h>
|
||||
#include <librr/alloc/generic.h>
|
||||
|
||||
typedef struct MtState * MtState;
|
||||
|
||||
struct MtState
|
||||
{
|
||||
char *app_name;
|
||||
|
||||
MtTagRegistry tag_registry;
|
||||
MtEntityRegistry entity_list;
|
||||
};
|
||||
|
||||
MtState mt_initialize(char *app_name);
|
||||
void mt_cleanup(MtState state);
|
||||
void mt_start(MtState state);
|
||||
|
||||
MtEntity mt_summon(MtState state);
|
||||
|
||||
#endif // MT_STATE_H
|
|
@ -0,0 +1,57 @@
|
|||
#include <entity.h>
|
||||
#include <state.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
MtEntity mt_create_entity(void *state_voidptr, u32_t identifier)
|
||||
{
|
||||
MtState state = state_voidptr;
|
||||
MtEntityListL1 *level1 = state->entity_list.lookup.sublists[identifier >> 24];
|
||||
if(level1 == NULL)
|
||||
{
|
||||
state->entity_list.lookup.sublists[identifier >> 24] = calloc(sizeof(MtEntityListL1), 1);
|
||||
level1 = state->entity_list.lookup.sublists[identifier >> 24];
|
||||
}
|
||||
|
||||
MtEntityListL2 *level2 = level1->sublists[(identifier >> 16) & 0xff];
|
||||
if(level2 == NULL)
|
||||
{
|
||||
level1->sublists[(identifier >> 16) & 0xff] = calloc(sizeof(MtEntityListL2), 1);
|
||||
level2 = level1->sublists[(identifier >> 16) & 0xff];
|
||||
}
|
||||
|
||||
MtEntityListL3 *level3 = level2->sublists[(identifier >> 8) & 0xff];
|
||||
if(level3 == NULL)
|
||||
{
|
||||
level2->sublists[(identifier >> 8) & 0xff] = calloc(sizeof(MtEntityListL3), 1);
|
||||
level3 = level2->sublists[(identifier >> 8) & 0xff];
|
||||
}
|
||||
|
||||
MtEntity entity = level3->entities[identifier & 0xff];
|
||||
if(entity == NULL)
|
||||
{
|
||||
entity = mt_get_entity_pool_slot(&state->entity_list.pool);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
MtEntity mt_get_entity(void *state_voidptr, u32_t identifier)
|
||||
{
|
||||
MtState state = state_voidptr;
|
||||
MtEntityListL1 *level1 = state->entity_list.lookup.sublists[identifier >> 24];
|
||||
if(level1 == NULL)
|
||||
return NULL;
|
||||
|
||||
MtEntityListL2 *level2 = level1->sublists[(identifier >> 16) & 0xff];
|
||||
if(level2 == NULL)
|
||||
return NULL;
|
||||
|
||||
MtEntityListL3 *level3 = level2->sublists[(identifier >> 8) & 0xff];
|
||||
if(level3 == NULL)
|
||||
return NULL;
|
||||
|
||||
MtEntity entity = level3->entities[identifier & 0xff];
|
||||
if(entity == NULL)
|
||||
return NULL;
|
||||
|
||||
return entity;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
#include <entity.h>
|
||||
#include <librr/memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void mt_delete_entity(MtEntity entity);
|
||||
|
||||
MtEntityLookupTree mt_create_entity_lookup_tree();
|
||||
void mt_delete_entity_lookup_tree(MtEntityLookupTree lookup_tree);
|
||||
|
||||
|
||||
|
||||
MtEntityRegistry mt_create_entity_registry()
|
||||
{
|
||||
MtEntityRegistry entity_registry;
|
||||
entity_registry.lookup = mt_create_entity_lookup_tree();
|
||||
return entity_registry;
|
||||
}
|
||||
|
||||
void mt_delete_entity_registry(MtEntityRegistry *entity_registry)
|
||||
{
|
||||
mt_delete_entity_pool(&entity_registry->pool);
|
||||
}
|
||||
|
||||
|
||||
|
||||
MtEntityLookupTree mt_create_entity_lookup_tree()
|
||||
{
|
||||
MtEntityLookupTree lookup_tree;
|
||||
rr_memset(&lookup_tree.sublists[0], sizeof(MtEntityListL1 *) * 256, 0x00);
|
||||
return lookup_tree;
|
||||
}
|
||||
|
||||
void mt_delete_entity_lookup_tree(MtEntityLookupTree lookup_tree)
|
||||
{
|
||||
usz_t level1_index = 0;
|
||||
while(level1_index < 256)
|
||||
{
|
||||
if(lookup_tree.sublists[level1_index] == NULL)
|
||||
{
|
||||
++level1_index;
|
||||
continue;
|
||||
}
|
||||
MtEntityListL1 *level1_list = lookup_tree.sublists[level1_index];
|
||||
usz_t level2_index = 0;
|
||||
while(level2_index < 256)
|
||||
{
|
||||
MtEntityListL2 *level2_list = level1_list->sublists[level2_index];
|
||||
if(level2_list == NULL)
|
||||
{
|
||||
++level2_index;
|
||||
continue;
|
||||
}
|
||||
usz_t level3_index = 0;
|
||||
while(level3_index)
|
||||
{
|
||||
MtEntityListL3 *level3_list = level2_list->sublists[level3_index];
|
||||
if(level3_list == NULL)
|
||||
{
|
||||
++level3_index;
|
||||
continue;
|
||||
}
|
||||
usz_t entity_index = 0;
|
||||
while(entity_index)
|
||||
{
|
||||
MtEntity entity = level3_list->entities[entity_index];
|
||||
if(entity == NULL)
|
||||
{
|
||||
++entity_index;
|
||||
continue;
|
||||
}
|
||||
mt_delete_entity(entity);
|
||||
++entity_index;
|
||||
}
|
||||
free(level3_list);
|
||||
++level3_index;
|
||||
}
|
||||
free(level2_list);
|
||||
++level2_index;
|
||||
}
|
||||
free(level1_list);
|
||||
++level1_index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mt_delete_entity(MtEntity entity)
|
||||
{
|
||||
if(entity->tags != NULL)
|
||||
free(entity->tags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mt_reset_entity_pool_allocation(MtEntityPool *pool)
|
||||
{
|
||||
usz_t entity_index = 0;
|
||||
while(entity_index < pool->capacity)
|
||||
{
|
||||
pool->entities[entity_index].pool_next_free = &pool->entities[entity_index+1];
|
||||
++entity_index;
|
||||
}
|
||||
pool->entities[pool->capacity - 1].pool_next_free = NULL;
|
||||
}
|
||||
|
||||
MtEntityPool mt_create_entity_pool(usz_t capacity)
|
||||
{
|
||||
MtEntityPool pool;
|
||||
pool.capacity = capacity;
|
||||
pool.entities = calloc(sizeof(struct MtEntity), pool.capacity);
|
||||
mt_reset_entity_pool_allocation(&pool);
|
||||
pool.first_free = &pool.entities[0];
|
||||
pool.continuation = NULL;
|
||||
return pool;
|
||||
}
|
||||
|
||||
void mt_delete_entity_pool(MtEntityPool *pool)
|
||||
{
|
||||
if(pool->continuation != NULL)
|
||||
{
|
||||
mt_delete_entity_pool(pool->continuation);
|
||||
free(pool->continuation);
|
||||
}
|
||||
free(pool->entities);
|
||||
}
|
||||
|
||||
|
||||
|
||||
MtEntity mt_get_entity_pool_slot(MtEntityPool *pool)
|
||||
{
|
||||
if(pool->first_free == NULL)
|
||||
{
|
||||
if(pool->continuation == NULL)
|
||||
{
|
||||
pool->continuation = malloc(sizeof(MtEntityPool));
|
||||
*pool->continuation = mt_create_entity_pool(pool->capacity * 2);
|
||||
}
|
||||
return mt_get_entity_pool_slot(pool->continuation);
|
||||
}
|
||||
MtEntity allocated = pool->first_free;
|
||||
pool->first_free = allocated->pool_next_free;
|
||||
return allocated;
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
#include <entity.h>
|
||||
#include <state.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
MtTag mt_get_entity_tag_slot(MtEntity entity, char *name)
|
||||
{
|
||||
MtState state = entity->parent_state;
|
||||
|
||||
// Find the correct slot if it already exist
|
||||
|
||||
u32_t tag_id = mt_get_tag_id(&state->tag_registry, name);
|
||||
usz_t tag_index = 0;
|
||||
while(tag_index < entity->num_tags)
|
||||
{
|
||||
if(entity->tags[tag_index].identifier == tag_id)
|
||||
return &entity->tags[tag_index];
|
||||
|
||||
++tag_index;
|
||||
}
|
||||
|
||||
// Create a new slot if needed
|
||||
|
||||
if(entity->num_tags >= entity->tags_capacity)
|
||||
{
|
||||
entity->tags_capacity *= 2;
|
||||
if(entity->tags_capacity == 0)
|
||||
entity->tags_capacity = 4;
|
||||
|
||||
entity->tags = realloc(entity->tags, sizeof(struct MtTag) * entity->tags_capacity);
|
||||
}
|
||||
return &entity->tags[entity->num_tags++];
|
||||
}
|
||||
|
||||
void mt_tag_i64(MtEntity entity, char *name, i64_t integer)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.integer = integer;
|
||||
}
|
||||
|
||||
void mt_tag_f64(MtEntity entity, char *name, f64_t real)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.real = real;
|
||||
}
|
||||
|
||||
void mt_tag_str(MtEntity entity, char *name, char *string)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.string = string;
|
||||
}
|
||||
|
||||
void mt_tag_ptr(MtEntity entity, char *name, void *pointer)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.pointer = pointer;
|
||||
}
|
||||
|
||||
void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.vec2f = vector;
|
||||
}
|
||||
|
||||
void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.vec3f = vector;
|
||||
}
|
||||
void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
tag->data.vec4f = vector;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mt_untag(MtEntity entity, char *name);
|
||||
|
||||
i64_t mt_get_i64_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.integer;
|
||||
}
|
||||
|
||||
f64_t mt_get_f64_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.real;
|
||||
}
|
||||
|
||||
char * mt_get_str_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.string;
|
||||
}
|
||||
|
||||
void * mt_get_ptr_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.pointer;
|
||||
}
|
||||
|
||||
rr_vec2f_s mt_get_vec2_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.vec2f;
|
||||
}
|
||||
|
||||
rr_vec3f_s mt_get_vec3_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.vec3f;
|
||||
}
|
||||
|
||||
rr_vec4f_s mt_get_vec4_tag(MtEntity entity, char *name)
|
||||
{
|
||||
MtTag tag = mt_get_entity_tag_slot(entity, name);
|
||||
return tag->data.vec4f;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#include <state.h>
|
||||
#include <librr/strutil.h>
|
||||
#include <librr/memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
MtState mt_initialize(char *app_name)
|
||||
{
|
||||
usz_t len_app_name = rr_measure_string(app_name);
|
||||
MtState state = malloc(sizeof(struct MtState));
|
||||
|
||||
state->app_name = malloc(len_app_name + 1);
|
||||
rr_memcopy(state->app_name, app_name, len_app_name + 1);
|
||||
state->tag_registry = mt_create_tag_registry(state);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void mt_cleanup(MtState state)
|
||||
{
|
||||
mt_delete_entity_registry(&state->entity_list);
|
||||
free(state);
|
||||
}
|
||||
|
||||
/* TODO: This function should start a new thread with a worker system.
|
||||
void mt_start(MtState state)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
Reference in New Issue