Implemented the core functionality of the ObjectStore and started
implementing the functionality for the AssetManager
This commit is contained in:
1 parent
79f28100bd
commit
c4f1775392
14 files changed
+330
-383
No files matched your search
+76
-139
@@ -1,25 +1,28 @@
|
||||
#include "ObjectStore.h"
|
||||
#include "Hashmap.h"
|
||||
#include "constants.h"
|
||||
#include "engine_build_config.h"
|
||||
#include "reusable_ids.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_ENGINE
|
||||
#include <stdio.h>
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
struct object_store {
|
||||
size_t count;
|
||||
int32_t active_indices[MAX_OBJ_COUNT];
|
||||
Hashmap *map;
|
||||
void **object_ptrs;
|
||||
EventHandlerPtr *event_handlers;
|
||||
UpdateFuncPtr *update_funcs;
|
||||
RenderFuncPtr *render_funcs;
|
||||
size_t deleted_count;
|
||||
ObjectID reusable_ids[MAX_OBJ_COUNT];
|
||||
void *object_ptrs[MAX_OBJ_COUNT];
|
||||
EventHandlerPtr event_handlers[MAX_OBJ_COUNT];
|
||||
UpdateFuncPtr update_funcs[MAX_OBJ_COUNT];
|
||||
RenderFuncPtr render_funcs[MAX_OBJ_COUNT];
|
||||
};
|
||||
|
||||
ObjectStore *create_object_store() {
|
||||
bool allocation_complete = true;
|
||||
|
||||
ObjectStore *os = (ObjectStore *)malloc(sizeof(ObjectStore));
|
||||
if (!os) {
|
||||
// If allocating memory to the store fails, we just return NULL. No need to
|
||||
@@ -27,149 +30,104 @@ ObjectStore *create_object_store() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os->map = create_hashmap();
|
||||
if (!(os->map)) {
|
||||
allocation_complete = false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
os->deleted_count = 0;
|
||||
memset(os->reusable_ids, 0, sizeof(os->reusable_ids));
|
||||
memset(os->object_ptrs, 0, sizeof(os->object_ptrs));
|
||||
memset(os->event_handlers, 0, sizeof(os->event_handlers));
|
||||
memset(os->update_funcs, 0, sizeof(os->update_funcs));
|
||||
memset(os->render_funcs, 0, sizeof(os->render_funcs));
|
||||
|
||||
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(os->map, object_tag);
|
||||
ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh,
|
||||
UpdateFuncPtr uf, RenderFuncPtr rf) {
|
||||
if (!os || !object ||
|
||||
(os->count + 1 == MAX_OBJ_COUNT && os->deleted_count == 0)) {
|
||||
#ifdef DEBUG_ENGINE
|
||||
printf("Failed to add object\n");
|
||||
#endif /* DEBUG_ENGINE */
|
||||
|
||||
if (index < 0) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
// TODO (Abdelrahman): Need to figure out a way to check that the object
|
||||
// hasn't already been added to the store. If it has been added before, the
|
||||
// function should return -1 indicating an error to ensure that there aren't
|
||||
// two references to the same object without the user being aware that they
|
||||
// refer to the same thing. If the user intentionally copies the ID of one
|
||||
// object, then it would be their responsibility to make sure they don't
|
||||
// delete the object using one of the IDs, then try to use it with the other.
|
||||
|
||||
ObjectID id;
|
||||
|
||||
if (os->deleted_count > 0) {
|
||||
id = (ObjectID)reuse_id((int32_t *)os->reusable_ids, os->deleted_count);
|
||||
os->deleted_count -= 1;
|
||||
os->count += 1;
|
||||
} else {
|
||||
id = (os->count)++;
|
||||
}
|
||||
|
||||
os->object_ptrs[id] = object;
|
||||
os->event_handlers[id] = eh;
|
||||
os->update_funcs[id] = uf;
|
||||
os->render_funcs[id] = rf;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void remove_object_from_store(ObjectStore *os, const char *object_tag) {
|
||||
if (os->count == 0) {
|
||||
void remove_object_from_store(ObjectStore *os, ObjectID id) {
|
||||
if (!os || os->count == 0 || !(os->object_ptrs[id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t index = delete_object_from_map(os->map, object_tag);
|
||||
os->object_ptrs[id] = NULL;
|
||||
os->event_handlers[id] = NULL;
|
||||
os->update_funcs[id] = NULL;
|
||||
os->render_funcs[id] = NULL;
|
||||
|
||||
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->reusable_ids[(os->deleted_count)++] = id;
|
||||
|
||||
os->count -= 1;
|
||||
}
|
||||
|
||||
void handle_all_objects_events(ObjectStore *os, const SDL_Event *event) {
|
||||
if (os->count == 0) {
|
||||
if (!os || os->count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < os->count; ++i) {
|
||||
int32_t index = os->active_indices[i];
|
||||
|
||||
if (os->event_handlers[index]) {
|
||||
void *object = os->object_ptrs[index];
|
||||
(os->event_handlers[index])(event, object);
|
||||
if (os->event_handlers[i]) {
|
||||
void *object = os->object_ptrs[i];
|
||||
(os->event_handlers[i])(event, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_all_objects(ObjectStore *os, float delta) {
|
||||
if (os->count == 0) {
|
||||
if (!os || os->count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < os->count; ++i) {
|
||||
int32_t index = os->active_indices[i];
|
||||
|
||||
if (os->update_funcs[index]) {
|
||||
void *object = os->object_ptrs[index];
|
||||
(os->update_funcs[index])(delta, object);
|
||||
if (os->update_funcs[i]) {
|
||||
void *object = os->object_ptrs[i];
|
||||
(os->update_funcs[i])(delta, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_all_objects(ObjectStore *os, Renderer *renderer) {
|
||||
if (os->count == 0) {
|
||||
if (!os || os->count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < os->count; ++i) {
|
||||
int32_t index = os->active_indices[i];
|
||||
|
||||
if (os->render_funcs[index]) {
|
||||
void *object = os->object_ptrs[index];
|
||||
(os->render_funcs[index])(renderer, object);
|
||||
if (os->render_funcs[i]) {
|
||||
void *object = os->object_ptrs[i];
|
||||
(os->render_funcs[i])(renderer, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,41 +137,20 @@ void destroy_object_store(ObjectStore *os) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < os->count; ++i) {
|
||||
os->active_indices[i] = -1;
|
||||
for (size_t i = 0; i < os->count; ++i) {
|
||||
os->object_ptrs[i] = NULL;
|
||||
os->event_handlers[i] = NULL;
|
||||
os->update_funcs[i] = NULL;
|
||||
os->render_funcs[i] = NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (os->map) {
|
||||
destroy_hashmap(os->map);
|
||||
os->map = NULL;
|
||||
}
|
||||
os->deleted_count = 0;
|
||||
|
||||
free(os);
|
||||
os = NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENGINE
|
||||
void print_objects(ObjectStore *os) { print_hashmap(os->map); }
|
||||
void print_objects(ObjectStore *os) {}
|
||||
#endif /* DEBUG_ENGINE */
|
||||
Reference in new issue
Block a user