Implemented the ObjectStore functionality.
This commit is contained in:
1 parent
20f476c4ab
commit
a0e76bc1fc
4 files changed
+257
-19
No files matched your search
+11
-1
@@ -1,13 +1,23 @@
|
|||||||
#ifndef HASHMAP_H
|
#ifndef HASHMAP_H
|
||||||
#define HASHMAP_H
|
#define HASHMAP_H
|
||||||
|
|
||||||
|
#include "engine_build_config.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENGINE
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif /* DEBUG_ENGINE */
|
||||||
|
|
||||||
void init_hashmap();
|
void init_hashmap();
|
||||||
int32_t add_object_to_map(const char *key);
|
int32_t add_object_to_map(const char *key);
|
||||||
int32_t get_object_index(const char *key);
|
int32_t get_object_index(const char *key);
|
||||||
void delete_object_from_map(const char *key);
|
int32_t delete_object_from_map(const char *key);
|
||||||
void destroy_hashmap();
|
void destroy_hashmap();
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENGINE
|
||||||
|
void print_hashmap();
|
||||||
|
void print_non_empty();
|
||||||
|
#endif // DEBUG_ENGINE
|
||||||
|
|
||||||
#endif // !HASHMAP_H
|
#endif // !HASHMAP_H
|
||||||
+11
-4
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
|
#include "engine_build_config.h"
|
||||||
|
|
||||||
typedef void (*EventHandlerPtr)(const SDL_Event *event, void *object);
|
typedef void (*EventHandlerPtr)(const SDL_Event *event, void *object);
|
||||||
typedef void (*UpdateFuncPtr)(float delta, void *object);
|
typedef void (*UpdateFuncPtr)(float delta, void *object);
|
||||||
@@ -10,12 +11,18 @@ typedef void (*RenderFuncPtr)(Renderer *renderer, void *object);
|
|||||||
|
|
||||||
typedef struct object_store ObjectStore;
|
typedef struct object_store ObjectStore;
|
||||||
|
|
||||||
void add_object_to_store(ObjectStore *os, const char *object_tag,
|
ObjectStore *create_object_store();
|
||||||
|
void add_object_to_store(ObjectStore *os, void *object, const char *object_tag,
|
||||||
EventHandlerPtr eh, UpdateFuncPtr uf,
|
EventHandlerPtr eh, UpdateFuncPtr uf,
|
||||||
RenderFuncPtr rf);
|
RenderFuncPtr rf);
|
||||||
void handle_all_object_events(ObjectStore *os);
|
|
||||||
void update_all_objects(ObjectStore *os);
|
|
||||||
void render_all_objects(ObjectStore *os);
|
|
||||||
void remove_object_from_store(ObjectStore *os, const char *object_tag);
|
void remove_object_from_store(ObjectStore *os, const char *object_tag);
|
||||||
|
void handle_all_objects_events(ObjectStore *os, const SDL_Event *event);
|
||||||
|
void update_all_objects(ObjectStore *os, float delta);
|
||||||
|
void render_all_objects(ObjectStore *os, Renderer *renderer);
|
||||||
|
void destroy_object_store(ObjectStore *os);
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENGINE
|
||||||
|
void print_objects();
|
||||||
|
#endif /* DEBUG_ENGINE */
|
||||||
|
|
||||||
#endif // !OBJECT_STORE_H
|
#endif // !OBJECT_STORE_H
|
||||||
+33
-14
@@ -18,11 +18,9 @@ INTERNAL struct objects_hashmap {
|
|||||||
} map = {};
|
} map = {};
|
||||||
|
|
||||||
void init_hashmap() {
|
void init_hashmap() {
|
||||||
// Technically, memset shouldn't be used to set the values of any thing other
|
for (int i = 0; i < MAX_OBJ_COUNT; ++i) {
|
||||||
// than byte arrays, but since it works in certain cases (e.g. 0 and -1) and
|
map.active_indices[i] = -1;
|
||||||
// it is faster than doing a for loop, I am using it here to initialise the
|
}
|
||||||
// active_indices array to -1
|
|
||||||
memset(map.active_indices, -1, sizeof(map.active_indices));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hash_key(const char *key) {
|
size_t hash_key(const char *key) {
|
||||||
@@ -95,13 +93,13 @@ int32_t get_object_index(const char *key) {
|
|||||||
return (int32_t)index;
|
return (int32_t)index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_object_from_map(const char *key) {
|
int32_t delete_object_from_map(const char *key) {
|
||||||
if (map.count == 0) {
|
if (map.count == 0) {
|
||||||
#ifdef DEBUG_ENGINE
|
#ifdef DEBUG_ENGINE
|
||||||
printf("Key \"%s\" doesn't exist\n", key);
|
printf("Key \"%s\" doesn't exist\n", key);
|
||||||
#endif /* DEBUG_ENGINE */
|
#endif /* DEBUG_ENGINE */
|
||||||
|
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = hash_key(key);
|
size_t index = hash_key(key);
|
||||||
@@ -111,7 +109,7 @@ void delete_object_from_map(const char *key) {
|
|||||||
printf("Key \"%s\" doesn't exist\n", key);
|
printf("Key \"%s\" doesn't exist\n", key);
|
||||||
#endif /* DEBUG_ENGINE */
|
#endif /* DEBUG_ENGINE */
|
||||||
|
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(map.keys[index]);
|
free(map.keys[index]);
|
||||||
@@ -140,6 +138,8 @@ void delete_object_from_map(const char *key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
map.count -= 1;
|
map.count -= 1;
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_hashmap() {
|
void destroy_hashmap() {
|
||||||
@@ -150,15 +150,34 @@ void destroy_hashmap() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (map.keys[index]) {
|
||||||
free(map.keys[index]);
|
free(map.keys[index]);
|
||||||
map.keys[index] = NULL;
|
map.keys[index] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
map.count = 0;
|
map.active_indices[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Technically, memset shouldn't be used to set the values of any thing other
|
map.count = 0;
|
||||||
// than byte arrays, but since it works in certain cases (e.g. 0 and -1) and
|
|
||||||
// it is faster than doing a for loop, I am using it here to initialise the
|
|
||||||
// active_indices array to -1
|
|
||||||
memset(map.active_indices, -1, sizeof(map.active_indices));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENGINE
|
||||||
|
void print_hashmap() {
|
||||||
|
if (map.count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < map.count; ++i) {
|
||||||
|
size_t index = map.active_indices[i];
|
||||||
|
printf("%d: %s\n", i, map.keys[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_non_empty() {
|
||||||
|
for (int i = 0; i < MAX_OBJ_COUNT; ++i) {
|
||||||
|
if (map.active_indices[i] != -1) {
|
||||||
|
printf("%d is not set to -1\n", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* DEBUG_ENGINE */
|
||||||
@@ -1 +1,203 @@
|
|||||||
#include "ObjectStore.h"
|
#include "ObjectStore.h"
|
||||||
|
#include "Hashmap.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct object_store {
|
||||||
|
size_t count;
|
||||||
|
int32_t active_indices[MAX_OBJ_COUNT];
|
||||||
|
void **object_ptrs;
|
||||||
|
EventHandlerPtr *event_handlers;
|
||||||
|
UpdateFuncPtr *update_funcs;
|
||||||
|
RenderFuncPtr *render_funcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
ObjectStore *create_object_store() {
|
||||||
|
init_hashmap();
|
||||||
|
|
||||||
|
bool allocation_complete = true;
|
||||||
|
|
||||||
|
ObjectStore *os = (ObjectStore *)malloc(sizeof(ObjectStore));
|
||||||
|
if (!os) {
|
||||||
|
// If allocating memory to the store fails, we still need to call the
|
||||||
|
// destroy function to make sure that the memory allocated for the
|
||||||
|
// hashmap is freed.
|
||||||
|
destroy_object_store(os);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->count = 0;
|
||||||
|
|
||||||
|
os->object_ptrs = malloc(sizeof(void *) * MAX_OBJ_COUNT);
|
||||||
|
if (!(os->object_ptrs)) {
|
||||||
|
allocation_complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->event_handlers =
|
||||||
|
(EventHandlerPtr *)malloc(sizeof(EventHandlerPtr) * MAX_OBJ_COUNT);
|
||||||
|
if (!(os->event_handlers)) {
|
||||||
|
allocation_complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->update_funcs =
|
||||||
|
(UpdateFuncPtr *)malloc(sizeof(UpdateFuncPtr) * MAX_OBJ_COUNT);
|
||||||
|
if (!(os->update_funcs)) {
|
||||||
|
allocation_complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->render_funcs =
|
||||||
|
(RenderFuncPtr *)malloc(sizeof(RenderFuncPtr) * MAX_OBJ_COUNT);
|
||||||
|
if (!(os->render_funcs)) {
|
||||||
|
allocation_complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allocation_complete) {
|
||||||
|
// If any of the allocations failed, we need to call the destroy function
|
||||||
|
// to free any resources that have been allocated successfully.
|
||||||
|
destroy_object_store(os);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_OBJ_COUNT; ++i) {
|
||||||
|
os->active_indices[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_object_to_store(ObjectStore *os, void *object, const char *object_tag,
|
||||||
|
EventHandlerPtr eh, UpdateFuncPtr uf,
|
||||||
|
RenderFuncPtr rf) {
|
||||||
|
int32_t index = add_object_to_map(object_tag);
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->active_indices[os->count] = index;
|
||||||
|
os->count += 1;
|
||||||
|
os->object_ptrs[index] = object;
|
||||||
|
os->event_handlers[index] = eh;
|
||||||
|
os->update_funcs[index] = uf;
|
||||||
|
os->render_funcs[index] = rf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_object_from_store(ObjectStore *os, const char *object_tag) {
|
||||||
|
if (os->count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t index = delete_object_from_map(object_tag);
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->object_ptrs[index] = NULL;
|
||||||
|
os->event_handlers[index] = NULL;
|
||||||
|
os->update_funcs[index] = NULL;
|
||||||
|
os->render_funcs[index] = NULL;
|
||||||
|
|
||||||
|
size_t packing_start_index = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < os->count; ++i) {
|
||||||
|
if (os->active_indices[i] == index) {
|
||||||
|
os->active_indices[i] = -1;
|
||||||
|
packing_start_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the indices are packed in the array
|
||||||
|
for (; packing_start_index < os->count; ++packing_start_index) {
|
||||||
|
if (packing_start_index + 1 == MAX_OBJ_COUNT) {
|
||||||
|
// Make sure we don't go out of bounds if we are at the last item
|
||||||
|
os->active_indices[packing_start_index] = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->active_indices[packing_start_index] =
|
||||||
|
os->active_indices[packing_start_index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
os->count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_all_objects_events(ObjectStore *os, const SDL_Event *event) {
|
||||||
|
if (os->count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < os->count; ++i) {
|
||||||
|
int32_t index = os->active_indices[i];
|
||||||
|
void *object = os->object_ptrs[index];
|
||||||
|
(os->event_handlers[index])(event, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_all_objects(ObjectStore *os, float delta) {
|
||||||
|
if (os->count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < os->count; ++i) {
|
||||||
|
int32_t index = os->active_indices[i];
|
||||||
|
void *object = os->object_ptrs[index];
|
||||||
|
(os->update_funcs[index])(delta, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_all_objects(ObjectStore *os, Renderer *renderer) {
|
||||||
|
if (os->count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < os->count; ++i) {
|
||||||
|
int32_t index = os->active_indices[i];
|
||||||
|
void *object = os->object_ptrs[index];
|
||||||
|
(os->render_funcs[index])(renderer, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_object_store(ObjectStore *os) {
|
||||||
|
destroy_hashmap();
|
||||||
|
|
||||||
|
if (!os) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < os->count; ++i) {
|
||||||
|
os->active_indices[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
os->count = 0;
|
||||||
|
|
||||||
|
if (os->event_handlers) {
|
||||||
|
free(os->event_handlers);
|
||||||
|
os->event_handlers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os->update_funcs) {
|
||||||
|
free(os->update_funcs);
|
||||||
|
os->update_funcs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os->render_funcs) {
|
||||||
|
free(os->render_funcs);
|
||||||
|
os->render_funcs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os->object_ptrs) {
|
||||||
|
free(os->object_ptrs);
|
||||||
|
os->object_ptrs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(os);
|
||||||
|
os = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENGINE
|
||||||
|
void print_objects() { print_hashmap(); }
|
||||||
|
#endif /* DEBUG_ENGINE */
|
||||||
Reference in new issue
Block a user