From 16b3293b41bca8f6d727ee2d13673a3b532fb0b3 Mon Sep 17 00:00:00 2001 From: shariq Date: Tue, 22 Aug 2017 18:28:24 +0500 Subject: [PATCH] Separated Game and Game Library code into executable and reloadable shared library --- README.md | 5 +- assets/keybindings.cfg | 1 + build/linux/makefile | 54 ++++++++++---- src/common.h | 131 ++++++++++++++++++++++++++++++++++ src/editor.c | 8 +-- src/entity.c | 60 +++++++++++++--- src/entity.h | 6 +- src/file_io.h | 8 +-- src/game.c | 85 ++++++++++++++-------- src/game.h | 4 +- src/geometry.c | 4 +- src/gl_load.c | 31 ++++---- src/gl_load.h | 5 +- src/gui.c | 15 ++-- src/input.c | 41 ++++++----- src/log.c | 21 ++++-- src/log.h | 16 +++-- src/main.c | 150 ++++++++++++++++++++++++++++++++++++--- src/platform.c | 63 ++++++++++++++++- src/platform.h | 16 ++--- src/renderer.c | 16 ++--- src/scene.c | 4 +- src/shader.c | 8 +-- src/sound.c | 157 +++++++++++++---------------------------- src/sound.h | 35 ++++----- src/texture.c | 4 +- src/variant.c | 17 +++++ src/variant.h | 3 + 28 files changed, 670 insertions(+), 298 deletions(-) create mode 100644 src/common.h diff --git a/README.md b/README.md index 8e6db7c..7f5a935 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,9 @@ - ## TODO + - Move game, common and game library related code into separate folders. + - Replace OpenAL with soloud + - Remove hardcoded numerical values from sscanf and other format strings. - Finish entity loading from file then move on to 2D rendering - First class 2d rendering - Sprite batching (XNA like) @@ -177,7 +180,6 @@ - Better handling incase assets folder is not found? - Write entity to/from file - Ogg format loading and playback - - Stick with OpenAL or switch to SoLoud + SDL for sound? - Sound streaming - Implment missing sound source properties (inner/outer cone, getting sound source data) - Ingame console and console commands etc @@ -296,3 +298,4 @@ * Fix camera acting all weird when right click is held * Fix README to conform with markdown syntax * Added video driver selection to make game launch under wayland or x11 on linux. + * Separate game code into a dynamical library that can be reloaded at runtime. diff --git a/assets/keybindings.cfg b/assets/keybindings.cfg index 603c2e1..d1dd1a0 100644 --- a/assets/keybindings.cfg +++ b/assets/keybindings.cfg @@ -12,3 +12,4 @@ Turn_Down : K Editor_Toggle : F1 Window_Fullscreen : F11 Window_Maximize : F12 +Reload_Game_Lib : Left Ctrl-Left Shift-R diff --git a/build/linux/makefile b/build/linux/makefile index 478a886..df12703 100644 --- a/build/linux/makefile +++ b/build/linux/makefile @@ -4,38 +4,55 @@ SRC_DIR = ../../src INCLUDE_DIR = ../../include DIST_DIR = ../../bin/linux BUILD_TYPE = release -SRCS = $(patsubst $(SRC_DIR)/%.c, %.c, $(wildcard ../../src/*.c)) -OBJS_RELEASE = $(patsubst %.c,.release/%.o,$(SRCS)) -OBJS_DEBUG = $(patsubst %.c,.debug/%.o,$(SRCS)) -CFLAGS = -Wall -I$(INCLUDE_DIR) -DUSE_GLAD -std=c99 $(shell pkg-config --cflags-only-other sdl2 openal) +CFLAGS = -Wall -I$(INCLUDE_DIR) -DUSE_GLAD -std=c99 +CFLAGS_GAME = $(CFLAGS) -DGAME $(shell pkg-config --cflags-only-other sdl2 openal) +CFLAGS_GAME_LIB = $(CFLAGS) -DGAME_LIB CFLAGS_DEBUG = -g -DGL_DEBUG_CONTEXT -DAL_DEBUG CFLAGS_RELEASE = -O3 -ffast-math -LFLAGS = $(shell pkg-config --libs sdl2 openal) -lm +LFLAGS = $(shell pkg-config --libs sdl2 openal) -lm -ldl ITCH_BUTLER = ~/.config/itch/bin/butler +SRCS_GAME = main.c platform.c log.c array.c utils.c config_vars.c file_io.c glad.c hashmap.c sound.c string_utils.c variant.c linmath.c +OBJS_RELEASE_GAME = $(patsubst %.c,.release/%.o,$(SRCS_GAME)) +OBJS_DEBUG_GAME = $(patsubst %.c,.debug/%.o,$(SRCS_GAME)) + +SRCS_GAME_LIB = gl_load.c glad.c log.c array.c utils.c hashmap.c string_utils.c variant.c linmath.c entity.c game.c transform.c camera.c renderer.c geometry.c light.c bounding_volumes.c editor.c framebuffer.c gui.c input.c material.c model.c scene.c shader.c texture.c +OBJS_RELEASE_GAME_LIB = $(patsubst %.c,.release/%.lib.o,$(SRCS_GAME_LIB)) +OBJS_DEBUG_GAME_LIB = $(patsubst %.c,.debug/%.lib.o,$(SRCS_GAME_LIB)) + all: release +library: CFLAGS_GAME_LIB += $(CFLAGS_DEBUG) +library: $(OBJS_RELEASE_GAME_LIB) + -@echo -e "\e[34mBuilding Game Lib\e[0m" + -@$(CC) -shared $(OBJS_RELEASE_GAME_LIB) -lm -o lib$(PROJECT_NAME).so + +.release/%.lib.o: $(SRC_DIR)/%.c + -@echo -e "\e[96mCompiling $<\e[0m" + -@$(CC) -fpic $(CFLAGS_GAME_LIB) -c $< -o $@ + + release: BUILD_TYPE = release -release: CFLAGS += $(CFLAGS_RELEASE) -release: pre_build $(OBJS_RELEASE) post_build +release: CFLAGS_GAME += $(CFLAGS_RELEASE) +release: pre_build $(OBJS_RELEASE_GAME) post_build -@echo -e "\e[34mLINKING\e[0m Release build" - -@$(CC) $(OBJS_RELEASE) $(LFLAGS) -o $(PROJECT_NAME) + -@$(CC) $(OBJS_RELEASE_GAME) $(LFLAGS) -o $(PROJECT_NAME) -@echo -e "\e[32mDONE\e[0m building $(PROJECT_NAME)" debug: BUILD_TYPE = debug -debug: CFLAGS += $(CFLAGS_DEBUG) -debug: pre_build $(OBJS_DEBUG) post_build +debug: CFLAGS_GAME += $(CFLAGS_DEBUG) +debug: pre_build $(OBJS_DEBUG_GAME) post_build -@echo -e "\e[34mLINKING\e[0m Debug build" - -@$(CC) $(OBJS_DEBUG) $(LFLAGS) -o $(PROJECT_NAME) + -@$(CC) $(OBJS_DEBUG_GAME) $(LFLAGS) -o $(PROJECT_NAME) -@echo -e "\e[32mDONE\e[0m building $(PROJECT_NAME)" .release/%.o: $(SRC_DIR)/%.c -@echo -e "\e[96mCompiling $<\e[0m" - -@$(CC) $(CFLAGS) -c $< -o $@ + -@$(CC) $(CFLAGS_GAME) -c $< -o $@ .debug/%.o: $(SRC_DIR)/%.c -@echo -e "\e[96mCompiling $<\e[0m" - -@$(CC) $(CFLAGS) -c $< -o $@ + -@$(CC) $(CFLAGS_GAME) -c $< -o $@ pre_build: -@mkdir -p .debug .release @@ -68,6 +85,13 @@ upload_itch: dist clean: -@echo -e "\e[31m" -rm -f $(PROJECT_NAME) - -rm -rf .release - -rm -rf .debug + -rm -rf .release/*.o + -rm -rf .debug/*.o + -@echo -e "\e[0m" + +clean_library: + -@echo -e "\e[31m" + -rm -f lib$(PROJECT_NAME).so + -rm -rf .release/*.lib.o + -rm -rf .debug/*.lib.o -@echo -e "\e[0m" diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..f9a74eb --- /dev/null +++ b/src/common.h @@ -0,0 +1,131 @@ +#ifndef COMMON_H +#define COMMON_H + +#include + +#include "num_types.h" + +#ifdef GAME_LIB +extern struct Platform_Api* platform; +#endif + +#ifdef GAME +extern struct Game_Api game; +#endif + +struct Window; +struct Hashmap; + +// Function Pointer decls +typedef void (*Keyboard_Event_Func) (int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); +typedef void (*Mousebutton_Event_Func) (int button, int state, int x, int y, int8 num_clicks); +typedef void (*Mousemotion_Event_Func) (int x, int y, int xrel, int yrel); +typedef void (*Mousewheel_Event_Func) (int x, int y); +typedef void (*Windowresize_Event_Func) (int x, int y); +typedef void (*Textinput_Event_Func) (const char* text); + +enum Directory_Type +{ + DT_USER, /* User directory or preferences directory */ + DT_INSTALL /* Directory where the game's executable is, usually where the game is installed */ +}; + +struct Sound_Api +{ + void (*volume_set)(float volume); + void (*listener_update)(float apos_x, float apos_y, float apos_z, + float afwd_x, float afwd_y, float afwd_z, + float aup_x, float aup_y, float aup_z); + void (*source_update)(uint source_handle, + float apos_x, float apos_y, float apos_z, + float afwd_x, float afwd_y, float afwd_z, + float aup_x, float aup_y, float aup_z); + void (*source_create)(bool relative, uint num_buffers, uint* out_handle, uint* out_buffer_handles); + void (*source_destroy)(uint source_handle, uint* attached_buffers, uint num_buffers); + void (*source_volume_set)(uint source_handle, float volume); + void (*source_pitch_set)(uint source_handle, float pitch); + void (*source_load_wav)(uint source_handle, uint buffer_handle, const char* file_name); + void (*source_loop_set)(uint source_handle, bool loop); + void (*source_relative_set)(uint source_handle, bool relative); + void (*source_play)(uint source_handle); + void (*source_pause)(uint source_handle); + void (*source_rewind)(uint source_handle); + void (*source_stop)(uint source_handle); +}; + +struct Window_Api +{ + struct Window* (*create)(const char* title, int width, int height, int msaa, int msaa_levels); + void (*destroy)(struct Window* window); + void (*show)(struct Window* window); + void (*hide)(struct Window* window); + void (*raise)(struct Window* window); + void (*make_context_current)(struct Window* window); + void (*set_size)(struct Window* window, int width, int height); + void (*get_size)(struct Window* window, int* out_width, int* out_height); + void (*get_drawable_size)(struct Window* window, int* out_width, int* out_height); + void (*swap_buffers)(struct Window* window); + int (*fullscreen_set)(struct Window* window, int fullscreen); +}; + +struct File_Api +{ + char* (*read)(const int directory_type, const char* path, const char* mode, long* file_size); + FILE* (*open)(const int directory_type, const char* path, const char* mode); +}; + +struct Config_Api +{ + bool (*load)(const char* filename, int directory_type); + bool (*save)(const char* filename, int directory_types); + struct Hashmap* (*get)(void); +}; + +struct Log_Api +{ + FILE* (*file_handle_get)(void); +}; + +struct Platform_Api +{ + // General platform api + void (*poll_events)(bool *out_quit); + void (*keyboard_callback_set)(Keyboard_Event_Func func); + void (*mousebutton_callback_set)(Mousebutton_Event_Func func); + void (*mousemotion_callback_set)(Mousemotion_Event_Func func); + void (*mousewheel_callback_set)(Mousewheel_Event_Func func); + void (*windowresize_callback_set)(Windowresize_Event_Func func); + void (*textinput_callback_set)(Textinput_Event_Func func); + int (*is_key_pressed)(int key); + int (*mousebutton_state_get)(uint button); + void (*mouse_position_get)(int* x, int* y); + void (*mouse_delta_get)(int* x, int* y); + void (*mouse_position_set)(struct Window* window, int x, int y); + void (*mouse_global_position_set)(int x, int y); + void (*mouse_relative_mode_set)(int relative_mode); + int (*mouse_relative_mode_get)(void); + uint32 (*ticks_get)(void); + char* (*install_directory_get)(void); + char* (*user_directory_get)(const char* organization, const char* application); + void (*clipboard_text_set)(const char* text); + char* (*clipboard_text_get)(void); + int (*key_from_name)(const char* key_name); + const char* (*key_name_get)(int key); + void* (*load_function_gl)(const char* name); + bool (*reload_game_lib)(void); + + struct Window_Api window; + struct Sound_Api sound; + struct File_Api file; + struct Config_Api config; + struct Log_Api log; +}; + +struct Game_Api +{ + bool (*init)(struct Window*, struct Platform_Api* platform_api); + void (*cleanup)(void); +}; + + +#endif diff --git a/src/editor.c b/src/editor.c index 028baf0..a8752e8 100644 --- a/src/editor.c +++ b/src/editor.c @@ -17,10 +17,8 @@ #include "array.h" #include "variant.h" #include "num_types.h" -#include "file_io.h" -#include "config_vars.h" #include "string_utils.h" -#include "platform.h" +#include "common.h" #include #include @@ -152,7 +150,7 @@ void editor_update(float dt) struct Gui_State* gui_state = gui_state_get(); struct nk_context* context = &gui_state->context; int win_width = 0, win_height = 0; - window_get_drawable_size(game_state->window, &win_width, &win_height); + platform->window.get_drawable_size(game_state->window, &win_width, &win_height); int half_width = win_width / 2, half_height = win_height / 2; static int window_flags = NK_WINDOW_BORDER | NK_WINDOW_CLOSABLE | @@ -189,7 +187,7 @@ void editor_update(float dt) if(nk_button_label(context, "Render Settings")) editor_state.renderer_settings_window = !editor_state.renderer_settings_window; if(nk_button_label(context, "Save config")) - config_vars_save("config.cfg", DT_USER); + platform->config.save("config.cfg", DT_USER); nk_spacing(context, 1); nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); nk_group_end(context); diff --git a/src/entity.c b/src/entity.c index bce5686..7f40c64 100644 --- a/src/entity.c +++ b/src/entity.c @@ -6,11 +6,10 @@ #include "camera.h" #include "light.h" #include "model.h" -#include "sound.h" #include "material.h" #include "geometry.h" #include "variant.h" -#include "file_io.h" +#include "common.h" #include #include @@ -51,8 +50,14 @@ void entity_remove(int index) { case ET_CAMERA: camera_destroy(entity); break; case ET_LIGHT: light_destroy(entity); break; - case ET_SOUND_SOURCE: sound_source_destroy(entity); break; case ET_STATIC_MESH: model_destroy(entity); break; + case ET_SOUND_SOURCE: + { + platform->sound.source_destroy(entity->sound_source.source_handle, + &entity->sound_source.buffer_handles[0], + entity->sound_source.num_attached_buffers); + } + break; case ET_ROOT: break; default: log_error("entity:remove", "Invalid entity type"); break; }; @@ -85,7 +90,7 @@ struct Entity* entity_create(const char* name, const int type, int parent_id) strncpy(new_entity->name, name ? name : "DEFAULT_ENTITY_NAME", MAX_ENTITY_NAME_LEN); new_entity->name[MAX_ENTITY_NAME_LEN - 1] = '\0'; new_entity->id = index; - new_entity->is_listener = false; + new_entity->is_listener = false; new_entity->type = type; new_entity->marked_for_deletion = false; new_entity->renderable = false; @@ -142,11 +147,37 @@ void entity_post_update(void) if(entity->transform.is_modified) { if(entity->type == ET_CAMERA) + { camera_update_view(entity); + } else if(entity->type == ET_SOUND_SOURCE) - sound_source_update(entity); - - if(entity->is_listener) sound_listener_update(); + { + vec3 abs_pos = {0.f, 0.f, 0.f}; + vec3 abs_fwd = {0.f, 0.f, -1.f}; + vec3 abs_up = {0.f, 1.f, 0.f}; + transform_get_absolute_pos(entity, &abs_pos); + transform_get_absolute_forward(entity, &abs_fwd); + transform_get_absolute_up(entity, &abs_up); + + platform->sound.source_update(entity->sound_source.source_handle, + abs_pos.x, abs_pos.y, abs_pos.z, + abs_fwd.x, abs_fwd.y, abs_fwd.z, + abs_up.x, abs_up.y, abs_up.z); + } + + if(entity->is_listener) + { + vec3 abs_pos = {0.f, 0.f, 0.f}; + vec3 abs_fwd = {0.f, 0.f, -1.f}; + vec3 abs_up = {0.f, 1.f, 0.f}; + transform_get_absolute_pos(entity, &abs_pos); + transform_get_absolute_forward(entity, &abs_fwd); + transform_get_absolute_up(entity, &abs_up); + + platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, + abs_fwd.x, abs_fwd.y, abs_fwd.z, + abs_up.x, abs_up.y, abs_up.z); + } } } } @@ -167,7 +198,7 @@ struct Entity* entity_get_parent(int node) bool entity_save(struct Entity* entity, const char* filename, int directory_type) { bool success = false; - FILE* entity_file = io_file_open(directory_type, filename, "w"); + FILE* entity_file = platform->file.open(directory_type, filename, "w"); if(!entity_file) { log_error("entity:save", "Failed to open entity file %s for writing"); @@ -254,7 +285,7 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type struct Entity* entity_load(const char* filename, int directory_type) { - FILE* entity_file = io_file_open(directory_type, filename, "r"); + FILE* entity_file = platform->file.open(directory_type, filename, "r"); if(!entity_file) { log_error("entity:load", "Failed to open entity file %s for writing", filename); @@ -466,6 +497,11 @@ struct Entity* entity_load(const char* filename, int directory_type) variant_from_str(&var_value, value_str, VT_BOOL); variant_copy_out(&entity.sound_source.relative, &var_value); } + else if(strncmp("num_attached_buffers", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + { + variant_from_str(&var_value, value_str, VT_INT); + variant_copy_out(&entity.sound_source.num_attached_buffers, &var_value); + } variant_free(&var_value); } @@ -478,7 +514,6 @@ struct Entity* entity_load(const char* filename, int directory_type) quat_assign(&new_entity->transform.rotation, &entity.transform.rotation); transform_scale(new_entity, &entity.transform.scale); - if(entity.is_listener) sound_listener_set(new_entity->id); if(entity.renderable) new_entity->renderable = true; switch(new_entity->type) @@ -497,7 +532,10 @@ struct Entity* entity_load(const char* filename, int directory_type) light_add(new_entity); break; case ET_SOUND_SOURCE: - sound_source_create(new_entity, new_entity->sound_source.relative); + platform->sound.source_create(new_entity->sound_source.relative, + new_entity->sound_source.num_attached_buffers, + &new_entity->sound_source.source_handle, + &new_entity->sound_source.buffer_handles[0]); break; }; diff --git a/src/entity.h b/src/entity.h index 09d1c65..82d4be1 100644 --- a/src/entity.h +++ b/src/entity.h @@ -5,6 +5,7 @@ #include "num_types.h" #define MAX_ENTITY_NAME_LEN 128 +#define MAX_SOUND_SOURCE_BUFFERS 5 struct Material_Param; @@ -51,8 +52,9 @@ struct Sound_Source { bool active; bool relative; - uint al_source_handle; - uint al_buffer_handle; + uint source_handle; + uint buffer_handles[MAX_SOUND_SOURCE_BUFFERS]; + uint num_attached_buffers; }; struct Camera diff --git a/src/file_io.h b/src/file_io.h index b18fef1..b6f2b3a 100644 --- a/src/file_io.h +++ b/src/file_io.h @@ -1,13 +1,7 @@ #ifndef FILE_IO_H #define FILE_IO_H -#include - -enum Directory_Type -{ - DT_USER, /* User directory or preferences directory */ - DT_INSTALL /* Directory where the game's executable is, usually where the game is installed */ -}; +#include "common.h" void io_file_init(const char* install_dir, const char* user_dir); char* io_file_read(const int directory_type, const char* path, const char* mode, long* file_size); diff --git a/src/game.c b/src/game.c index e4856c2..06692fe 100644 --- a/src/game.c +++ b/src/game.c @@ -2,13 +2,12 @@ #include #include #include +#include #include "game.h" -#include "platform.h" #include "input.h" #include "renderer.h" #include "log.h" -#include "file_io.h" #include "shader.h" #include "entity.h" #include "geometry.h" @@ -24,11 +23,11 @@ #include "light.h" #include "gl_load.h" #include "gui.h" -#include "sound.h" #include "editor.h" #include "config_vars.h" #include "hashmap.h" #include "variant.h" +#include "common.h" #define UNUSED(a) (void)a #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -38,7 +37,7 @@ #define MAX_FRAME_TIME 0.5f -static int run(void); +static bool run(void); static void update(float dt, bool* window_should_close); static void render(void); static void debug(float dt); @@ -46,9 +45,18 @@ static void debug_gui(float dt); static void scene_setup(void); static struct Game_State* game_state = NULL; +struct Platform_Api* platform = NULL; -int game_init(struct Window* window) +bool game_init(struct Window* window, struct Platform_Api* platform_api) { + if(!platform_api) + { + log_error("game:init", "Platform api not passed in!"); + return false; + } + + platform = malloc(sizeof(*platform)); + memcpy(platform, platform_api, sizeof(*platform_api)); game_state = malloc(sizeof(*game_state)); if(!game_state) { @@ -65,8 +73,17 @@ int game_init(struct Window* window) /* TODO: Decouple systems' init/cleanup from game, they should exist and run even if there's no "game" */ /* Init systems */ + log_file_handle_set(platform->log.file_handle_get()); + if(!gl_load_extentions()) + { + log_error("game:init", "Failed to load GL extentions"); + return false; + } + else + { + log_message("Loaded GL extentions"); + } input_init(); - sound_init(); shader_init(); texture_init(); framebuffer_init(); @@ -96,7 +113,6 @@ void scene_setup(void) camera_create(player, render_width, render_height); camera_attach_fbo(player, render_width, render_height, 1, 1, 1); vec4_fill(&player->camera.clear_color, 0.3f, 0.6f, 0.9f, 1.0f); - sound_listener_set(player->id); vec4 color = {1.f, 1.f, 1.f, 1.f }; struct Entity* new_ent = scene_add_new("Model_Entity", ET_STATIC_MESH); @@ -111,12 +127,15 @@ void scene_setup(void) transform_scale(new_ent, &scale); struct Entity* sound_ent = scene_add_as_child("Sound_ENT", ET_SOUND_SOURCE, new_ent->id); - sound_source_create(sound_ent, false); - sound_source_load_wav(sound_ent, "BigExplosion.wav"); + struct Sound_Source* sound_source = &sound_ent->sound_source; + platform->sound.source_create(true, 1, &sound_source->source_handle, &sound_source->buffer_handles[0]); + platform->sound.source_load_wav(sound_source->source_handle, + sound_source->buffer_handles[0], + "BigExplosion.wav"); //sound_source_relative_set(source, true); - sound_source_volume_set(sound_ent, 1.f); - sound_source_loop_set(sound_ent, true); - sound_source_play(sound_ent); + platform->sound.source_volume_set(sound_source->source_handle, 1.f); + platform->sound.source_loop_set(sound_source->source_handle, true); + platform->sound.source_play(sound_source->source_handle); int parent_node = new_ent->id; int num_suz = 50; @@ -220,12 +239,12 @@ void debug(float dt) turn_up_down = -cursor_ud * turn_speed * dt * scale; turn_left_right = cursor_lr * turn_speed * dt * scale; - log_message("ud : %d, lr : %d", cursor_ud, cursor_lr); +// log_message("ud : %d, lr : %d", cursor_ud, cursor_lr); } else { input_mouse_mode_set(MM_NORMAL); - log_message("ud : %.3f, lr : %.3f", turn_up_down, turn_left_right); +// log_message("ud : %.3f, lr : %.3f", turn_up_down, turn_left_right); turn_up_down *= dt; turn_left_right *= dt; } @@ -308,42 +327,43 @@ void debug(float dt) transform_translate(model, &amount, TS_LOCAL); } - /* struct Entity* model = scene_find("Light_Ent"); */ - /* vec3 x_axis = {0, 1, 0}; */ - /* transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); */ - /* vec3 amount = {0, 0, -5 * dt}; */ - /* transform_translate(model, &amount, TS_LOCAL); */ + struct Entity* model = scene_find("Model_Entity"); + vec3 x_axis = {0, 1, 0}; + transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); + vec3 amount = {0, 0, -5 * dt}; + transform_translate(model, &amount, TS_LOCAL); } -int run(void) +bool run(void) { - uint32 last_time = platform_ticks_get(); + uint32 last_time = platform->ticks_get(); bool should_window_close = 0; while(!should_window_close) { - uint32 curr_time = platform_ticks_get(); + uint32 curr_time = platform->ticks_get(); float delta_time = (float)(curr_time - last_time) / 1000.f; last_time = curr_time; if(delta_time > MAX_FRAME_TIME) delta_time = (1.f / 60.f); /* To deal with resuming from breakpoint we artificially set delta time */ gui_input_begin(); - platform_poll_events(&should_window_close); + platform->poll_events(&should_window_close); gui_input_end(); update(delta_time, &should_window_close); render(); - window_swap_buffers(game_state->window); + platform->window.swap_buffers(game_state->window); entity_post_update(); } - return 1; + return true; } void update(float dt, bool* window_should_close) { if(input_is_key_pressed(KEY_ESCAPE)) *window_should_close = true; if(input_map_state_get("Editor_Toggle", KS_RELEASED)) editor_toggle(); - if(input_map_state_get("Window_Fullscreen", KS_RELEASED)) window_fullscreen_set(game_state->window, 1); - if(input_map_state_get("Window_Maximize", KS_RELEASED)) window_fullscreen_set(game_state->window, 0); + if(input_map_state_get("Window_Fullscreen", KS_RELEASED)) platform->window.fullscreen_set(game_state->window, 1); + if(input_map_state_get("Window_Maximize", KS_RELEASED)) platform->window.fullscreen_set(game_state->window, 0); + if(input_map_state_get("Reload_Game_Lib", KS_RELEASED)) platform->reload_game_lib(); debug(dt); //debug_gui(dt); @@ -1576,20 +1596,23 @@ void game_cleanup(void) light_cleanup(); input_cleanup(); renderer_cleanup(); - io_file_cleanup(); framebuffer_cleanup(); texture_cleanup(); shader_cleanup(); - sound_cleanup(); - window_destroy(game_state->window); - gl_cleanup(); } free(game_state); game_state = NULL; } + + if(platform) free(platform); } struct Game_State* game_state_get(void) { return game_state; } + +void game_test(const char *str) +{ + log_message("Func called!"); +} diff --git a/src/game.h b/src/game.h index 2ee0422..13269c6 100644 --- a/src/game.h +++ b/src/game.h @@ -4,6 +4,7 @@ #include struct Window; +struct Platform_Api; struct Game_State { @@ -15,7 +16,8 @@ struct Game_State struct Game_State* game_state_get(void); -int game_init(struct Window* window); +bool game_init(struct Window* window, struct Platform_Api* platform_api); void game_cleanup(void); +void game_test(const char* str); #endif diff --git a/src/geometry.c b/src/geometry.c index 3de47a8..64fe85d 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -1,10 +1,10 @@ #include "geometry.h" #include "array.h" #include "string_utils.h" -#include "file_io.h" #include "log.h" #include "renderer.h" #include "transform.h" +#include "common.h" #include "gl_load.h" #include @@ -214,7 +214,7 @@ static int load_from_file(struct Geometry* geometry, const char* filename) int success = 1; char* full_path = str_new("models/%s", filename); - FILE* file = io_file_open(DT_INSTALL, full_path, "rb"); + FILE* file = platform->file.open(DT_INSTALL, full_path, "rb"); free(full_path); if(file) { diff --git a/src/gl_load.c b/src/gl_load.c index e30296d..66370eb 100644 --- a/src/gl_load.c +++ b/src/gl_load.c @@ -1,6 +1,6 @@ #include "gl_load.h" #include "log.h" -#include +#include "common.h" #ifndef USE_GLAD @@ -14,23 +14,23 @@ SYMMETRY_GL_LIST int gl_load_library(void) { int success = 1; - if(SDL_GL_LoadLibrary(NULL) < 0) - { - success = 0; - log_error("gl_load_library", "Failed to load GL library %s", SDL_GetError()); - } - else - { - log_message("Loaded GL library"); - } +// if(SDL_GL_LoadLibrary(NULL) < 0) +// { +// success = 0; +// log_error("gl_load_library", "Failed to load GL library %s", SDL_GetError()); +// } +// else +// { +// log_message("Loaded GL library"); +// } return success; } -int gl_load_extentions(void) +bool gl_load_extentions(void) { - int success = 1; + bool success = true; #ifdef USE_GLAD - if(!gladLoadGLLoader(&SDL_GL_GetProcAddress)) success = 0; + if(!gladLoadGLLoader(platform->load_function_gl)) success = false; #else #define GLE(ret, name, ...) \ @@ -45,8 +45,3 @@ int gl_load_extentions(void) #endif return success; } - -void gl_cleanup(void) -{ - SDL_GL_UnloadLibrary(); -} diff --git a/src/gl_load.h b/src/gl_load.h index bb9e79a..7d62a21 100644 --- a/src/gl_load.h +++ b/src/gl_load.h @@ -2,7 +2,10 @@ #define GL_LOAD_H #ifdef USE_GLAD + #include +#include + #else #include @@ -60,7 +63,7 @@ SYMMETRY_GL_LIST #endif int gl_load_library(void); -int gl_load_extentions(void); +bool gl_load_extentions(void); void gl_cleanup(void); #endif diff --git a/src/gui.c b/src/gui.c index a0a7deb..db8be8b 100644 --- a/src/gui.c +++ b/src/gui.c @@ -1,6 +1,5 @@ #define NK_IMPLEMENTATION #include "gui.h" -#include "platform.h" #include "linmath.h" #include "log.h" #include "shader.h" @@ -8,8 +7,8 @@ #include "game.h" #include "input.h" #include "renderer.h" -#include "file_io.h" #include "string_utils.h" +#include "common.h" #include #include @@ -89,7 +88,7 @@ bool gui_init(void) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); - platform_textinput_callback_set(&gui_handle_textinput_event); + platform->textinput_callback_set(&gui_handle_textinput_event); //gui_font_set("Ubuntu-R.ttf", 14); //gui_font_set("FiraSans-Regular.ttf", 14); gui_font_set("RobotoCondensed-Regular.ttf", 18); @@ -133,8 +132,8 @@ void gui_render(enum nk_anti_aliasing AA) mat4_identity(&gui_mat); struct Game_State* game_state = game_state_get(); - window_get_size(game_state->window, &width, &height); - window_get_drawable_size(game_state->window, &display_width, &display_height); + platform->window.get_size(game_state->window, &width, &height); + platform->window.get_drawable_size(game_state->window, &display_width, &display_height); mat4_ortho(&gui_mat, 0, display_width, display_height, 0, -100, 100); scale.x = (float)display_width/(float)width; @@ -227,7 +226,7 @@ void gui_render(enum nk_anti_aliasing AA) void gui_handle_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) { - char *text = platform_clipboard_text_get(); + char *text = platform->clipboard_text_get(); if(text) { nk_textedit_paste(edit, text, nk_strlen(text)); @@ -245,7 +244,7 @@ void gui_handle_clipbard_copy(nk_handle usr, const char *text, int len) if (!str) return; memcpy(str, text, (size_t)len); str[len] = '\0'; - platform_clipboard_text_set(str); + platform->clipboard_text_set(str); free(str); } @@ -373,7 +372,7 @@ void gui_font_set(const char* font_name, float font_size) struct nk_font_atlas* atlas = &gui_state->atlas; long size = 0; char* font_file_name = str_new("fonts/%s", font_name); - char* font_data = io_file_read(DT_INSTALL, font_file_name, "rb", &size); + char* font_data = platform->file.read(DT_INSTALL, font_file_name, "rb", &size); free(font_file_name); if(!font_data) { diff --git a/src/input.c b/src/input.c index 6b429be..2726994 100644 --- a/src/input.c +++ b/src/input.c @@ -3,11 +3,10 @@ #include #include "input.h" #include "array.h" -#include "platform.h" #include "log.h" #include "gui.h" -#include "file_io.h" #include "string_utils.h" +#include "common.h" struct Input_Map { @@ -26,10 +25,10 @@ static struct Input_Map* input_map_list = NULL; void input_init(void) { - platform_keyboard_callback_set(&input_on_key); - platform_mousebutton_callback_set(&input_on_mousebutton); - platform_mousemotion_callback_set(&input_on_mousemotion); - platform_mousewheel_callback_set(&input_on_mousewheel); + platform->keyboard_callback_set(&input_on_key); + platform->mousebutton_callback_set(&input_on_mousebutton); + platform->mousemotion_callback_set(&input_on_mousemotion); + platform->mousewheel_callback_set(&input_on_mousewheel); input_map_list = array_new(struct Input_Map); if(!input_keybinds_load("keybindings.cfg", DT_USER)) @@ -95,7 +94,7 @@ bool input_keybinds_load(const char* filename, int directory_type) bool success = false; const int MAX_KEYBIND_LEN = 128; const int MAX_LINE_LEN = 512; - FILE* config_file = io_file_open(directory_type, filename, "r"); + FILE* config_file = platform->file.open(directory_type, filename, "r"); if(!config_file) { log_error("input:keybinds_load", "Could not open %s", filename); @@ -157,7 +156,7 @@ bool input_keybinds_load(const char* filename, int directory_type) strncpy(key_name, start_loc, (keys - start_loc)); //log_message("key_name : %s", key_name); - int key_modifier = platform_key_from_name(key_name); + int key_modifier = platform->key_from_name(key_name); if(key_modifier == KEY_UNKNOWN) { @@ -185,7 +184,7 @@ bool input_keybinds_load(const char* filename, int directory_type) /* Copy the last key after the hyphen */ strncpy(key_name, start_loc, max_key_str_len); - int key = platform_key_from_name(key_name); + int key = platform->key_from_name(key_name); if(key == KEY_UNKNOWN) { log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); @@ -209,7 +208,7 @@ bool input_keybinds_save(const char* filename) { bool success = false; - FILE* config_file = io_file_open(DT_USER, filename, "w"); + FILE* config_file = platform->file.open(DT_USER, filename, "w"); if(!config_file) { log_error("input:keybinds_save", "Could not open %s", filename); @@ -224,10 +223,10 @@ bool input_keybinds_save(const char* filename) { if(j != 0) fprintf(config_file, ", "); struct Key_Combination* key_comb = &map->keys[j]; - if((key_comb->mods & KMD_ALT) == KMD_ALT) fprintf(config_file, "%s-", platform_key_name_get(KEY_LALT)); - if((key_comb->mods & KMD_SHIFT) == KMD_SHIFT) fprintf(config_file, "%s-", platform_key_name_get(KEY_LSHIFT)); - if((key_comb->mods & KMD_CTRL) == KMD_CTRL) fprintf(config_file, "%s-", platform_key_name_get(KEY_LCTRL)); - fprintf(config_file, "%s", platform_key_name_get(key_comb->key)); + if((key_comb->mods & KMD_ALT) == KMD_ALT) fprintf(config_file, "%s-", platform->key_name_get(KEY_LALT)); + if((key_comb->mods & KMD_SHIFT) == KMD_SHIFT) fprintf(config_file, "%s-", platform->key_name_get(KEY_LSHIFT)); + if((key_comb->mods & KMD_CTRL) == KMD_CTRL) fprintf(config_file, "%s-", platform->key_name_get(KEY_LCTRL)); + fprintf(config_file, "%s", platform->key_name_get(key_comb->key)); } fprintf(config_file, "\n"); } @@ -253,12 +252,12 @@ void input_on_mousewheel(int x, int y) void input_mouse_pos_get(int* xpos, int* ypos) { assert(xpos && ypos); - platform_mouse_position_get(xpos, ypos); + platform->mouse_position_get(xpos, ypos); } void input_mouse_pos_set(int xpos, int ypos) { - platform_mouse_global_position_set(xpos, ypos); + platform->mouse_global_position_set(xpos, ypos); } void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt) @@ -300,7 +299,7 @@ void input_on_mousebutton(int button, int state, int x, int y, int8 num_clicks) void input_mouse_mode_set(enum Mouse_Mode mode) { - platform_mouse_relative_mode_set(mode == MM_NORMAL ? 0 : 1); + platform->mouse_relative_mode_set(mode == MM_NORMAL ? 0 : 1); } bool input_map_state_get(const char* map_name, int state) @@ -326,12 +325,12 @@ bool input_map_state_get(const char* map_name, int state) bool input_is_key_pressed(int key) { - return platform_is_key_pressed(key); + return platform->is_key_pressed(key); } bool input_mousebutton_state_get(uint button, int state_type) { - int current_state = platform_mousebutton_state_get(button); + int current_state = platform->mousebutton_state_get(button); return state_type == current_state ? true : false; } @@ -440,12 +439,12 @@ int map_find(const char* name) int input_mouse_mode_get(void) { int mouse_mode = MM_NORMAL; - if(platform_mouse_relative_mode_get()) mouse_mode = MM_RELATIVE; + if(platform->mouse_relative_mode_get()) mouse_mode = MM_RELATIVE; return mouse_mode; } void input_mouse_delta_get(int* xpos, int* ypos) { - platform_mouse_delta_get(xpos, ypos); + platform->mouse_delta_get(xpos, ypos); } diff --git a/src/log.c b/src/log.c index 80151a5..b515f97 100644 --- a/src/log.c +++ b/src/log.c @@ -4,7 +4,6 @@ #include #include "log.h" -#include "platform.h" #ifdef __linux__ #define COLOURED_STDOUT @@ -32,15 +31,14 @@ static FILE* log_file = NULL; -void log_init(const char* log_file_name) +void log_init(const char* log_file_name, const char* user_directory) { - char* dir = platform_user_directory_get("SS_Games", "Symmetry"); char log_file_path[512] = {'\0'}; - snprintf(log_file_path, 512, "%s/%s", dir, log_file_name); + snprintf(log_file_path, 512, "%s/%s", user_directory, log_file_name); log_file = fopen(log_file_path, "w"); if(!log_file) { - log_to_stdout("ERR: (log:init): Failed to create log file at %s", dir); + log_to_stdout("ERR: (log:init): Failed to create log file at %s", user_directory); } else { @@ -49,7 +47,8 @@ void log_init(const char* log_file_name) fprintf(log_file, "Log Initialized at %s\n", ctime(¤t_time)); fflush(log_file); } - if(dir) free(dir); + // Disable stdout buffering + setbuf(stdout, NULL); } void log_cleanup(void) @@ -115,3 +114,13 @@ void log_error(const char* context, const char* error, ...) fprintf(log_file, "\n"); fflush(log_file); } + +FILE* log_file_handle_get(void) +{ + return log_file; +} + +void log_file_handle_set(FILE* file) +{ + log_file = file; +} diff --git a/src/log.h b/src/log.h index 6e95045..256d028 100644 --- a/src/log.h +++ b/src/log.h @@ -1,11 +1,15 @@ #ifndef LOG_H #define LOG_H -void log_init(const char* log_file_name); -void log_cleanup(void); -void log_message(const char* message, ...); -void log_warning(const char* message, ...); -void log_error(const char* context, const char* error, ...); -void log_to_stdout(const char* message, ...); /* Only use when logging is not initialized */ +#include + +void log_init(const char* log_file_name, const char* user_directory); +void log_cleanup(void); +void log_message(const char* message, ...); +void log_warning(const char* message, ...); +void log_error(const char* context, const char* error, ...); +void log_to_stdout(const char* message, ...); /* Only use when logging is not initialized */ +FILE* log_file_handle_get(void); +void log_file_handle_set(FILE* file); #endif diff --git a/src/main.c b/src/main.c index 0782177..e30e041 100644 --- a/src/main.c +++ b/src/main.c @@ -2,24 +2,109 @@ #include #include "log.h" +#include "sound.h" #include "platform.h" #include "gl_load.h" -#include "game.h" #include "file_io.h" #include "config_vars.h" #include "hashmap.h" +#include "common.h" static struct Window* window = NULL; +static struct Platform_Api platform_api; +struct Game_Api game; +void* game_lib_handle = NULL; -bool init(); -void cleanup(); +bool init(void); +void cleanup(void); +bool game_lib_load(void); +bool game_lib_reload(void); int main(int argc, char** args) { if(!init()) + { log_to_stdout("ERR:(Main) Could not initialize"); + } else - game_init(window); + { + platform_api = (struct Platform_Api) + { + .poll_events = &platform_poll_events, + .keyboard_callback_set = &platform_keyboard_callback_set, + .mousebutton_callback_set = &platform_mousebutton_callback_set, + .mousemotion_callback_set = &platform_mousemotion_callback_set, + .mousewheel_callback_set = &platform_mousewheel_callback_set, + .windowresize_callback_set = &platform_windowresize_callback_set, + .textinput_callback_set = &platform_textinput_callback_set, + .is_key_pressed = &platform_is_key_pressed, + .mousebutton_state_get = &platform_mousebutton_state_get, + .mouse_position_get = &platform_mouse_position_get, + .mouse_delta_get = &platform_mouse_delta_get, + .mouse_position_set = &platform_mouse_position_set, + .mouse_global_position_set = &platform_mouse_global_position_set, + .mouse_relative_mode_set = &platform_mouse_relative_mode_set, + .mouse_relative_mode_get = &platform_mouse_relative_mode_get, + .ticks_get = &platform_ticks_get, + .install_directory_get = &platform_install_directory_get, + .user_directory_get = &platform_user_directory_get, + .clipboard_text_set = &platform_clipboard_text_set, + .clipboard_text_get = &platform_clipboard_text_get, + .key_from_name = &platform_key_from_name, + .key_name_get = &platform_key_name_get, + .load_function_gl = &platform_load_function_gl, + .reload_game_lib = &game_lib_reload, + .sound = + { + .volume_set = &sound_volume_set, + .listener_update = &sound_listener_update, + .source_update = &sound_source_update, + .source_create = &sound_source_create, + .source_destroy = &sound_source_destroy, + .source_volume_set = &sound_source_volume_set, + .source_pitch_set = &sound_source_pitch_set, + .source_load_wav = &sound_source_load_wav, + .source_loop_set = &sound_source_loop_set, + .source_relative_set = &sound_source_relative_set, + .source_play = &sound_source_play, + .source_pause = &sound_source_pause, + .source_rewind = &sound_source_rewind, + .source_stop = &sound_source_stop + }, + .window = + { + .create = &window_create, + .destroy = &window_destroy, + .show = &window_show, + .raise = &window_raise, + .make_context_current = &window_make_context_current, + .set_size = &window_set_size, + .get_size = &window_get_size, + .get_drawable_size = &window_get_drawable_size, + .swap_buffers = &window_swap_buffers, + .fullscreen_set = &window_fullscreen_set + }, + .file = + { + .read = &io_file_read, + .open = &io_file_open + }, + .config = + { + .load = &config_vars_load, + .save = &config_vars_save, + .get = &config_vars_get + }, + .log = + { + .file_handle_get = &log_file_handle_get + } + }; + if(!game_lib_load()) + log_error("main", "Failed to load game library"); + else + game.init(window, &platform_api); + } exit(EXIT_SUCCESS); } @@ -35,10 +120,9 @@ bool init(void) config_vars_init(); if(!platform_init()) return false; - log_init("Log.txt"); - char* install_path = platform_install_directory_get(); char* user_path = platform_user_directory_get("SS_Games", "Symmetry"); + log_init("Log.txt", user_path); io_file_init(install_path, user_path); free(install_path); free(user_path); @@ -50,7 +134,7 @@ bool init(void) if(!platform_init_video()) return false; - if(!gl_load_library()) + if(!platform_load_gl(NULL)) { log_error("main:init", "Initializing OpenGL failed"); return false; @@ -68,9 +152,15 @@ bool init(void) return false; } - if(!gl_load_extentions()) +// if(!gl_load_extentions()) +// { +// log_error("main:init", "Failed to load opengl extentions"); +// return false; +// } + + if(!sound_init()) { - log_error("main:init", "Failed to load opengl extentions"); + log_error("main:init", "Failed to initialize sound"); return false; } @@ -79,9 +169,49 @@ bool init(void) void cleanup() { - game_cleanup(); + if(game.cleanup) game.cleanup(); + if(window) window_destroy(window); + if(game_lib_handle) platform_unload_library(game_lib_handle); + sound_cleanup(); + platform_unload_gl(); platform_cleanup(); config_vars_cleanup(); + io_file_cleanup(); log_message("Program exiting!"); log_cleanup(); } + +bool game_lib_reload(void) +{ + if(game_lib_handle) + { + if(game.cleanup) game.cleanup(); + platform_unload_library(game_lib_handle); + } + if(!game_lib_load()) + { + log_error("main:game_lib_reload", "Failed to reload game library"); + return false; + } + + return game.init(window, &platform_api); +} + +bool game_lib_load(void) +{ + game_lib_handle = platform_load_library("Symmetry"); + if(!game_lib_handle) + { + log_error("main:game_lib_load", "Failed to load game library"); + return false; + } + + log_message("Game library loaded"); + game.init = platform_load_function(game_lib_handle, "game_init"); + game.cleanup = platform_load_function(game_lib_handle, "game_cleanup"); + if(!game.init && !game.cleanup) + return false; + + log_message("Game api loaded"); + return true; +} diff --git a/src/platform.c b/src/platform.c index 6e55929..3f0b4ac 100644 --- a/src/platform.c +++ b/src/platform.c @@ -1,12 +1,13 @@ #include "platform.h" #include "log.h" -#include "input.h" #include "config_vars.h" #include "hashmap.h" #include "string_utils.h" -#include -static int current_video_driver = VD_DUMMY; +#include +#include +#include +#include struct Window { @@ -451,3 +452,59 @@ char* platform_user_directory_get(const char* organization, const char* applicat } return user_directory; } + +void* platform_load_library(const char *name) +{ +#define MAX_LIB_NAME_LEN 256 + char lib_name[MAX_LIB_NAME_LEN]; + memset(lib_name, '\0', MAX_LIB_NAME_LEN); +#ifdef __linux__ + snprintf(lib_name, MAX_LIB_NAME_LEN, "./lib%s.so", name); +#else + snprintf(lib_name, MAX_LIB_NAME_LEN, "%s.dll", name); +#endif + void* lib_handle = SDL_LoadObject(lib_name); + if(!lib_handle) log_error("platform:load_library", "Failed to load library '%s', SDL : (%s)", lib_name, SDL_GetError()); + return lib_handle; +} + +void* platform_load_function(void *library_handle, const char *func_name) +{ + assert(library_handle); + void* func_ptr = SDL_LoadFunction(library_handle, func_name); + if(!func_ptr) log_error("platform:load_function", "Failed to load function '%s' from library, SDL : (%s)", func_name, SDL_GetError()); + return func_ptr; +} + +void platform_unload_library(void* library_handle) +{ + assert(library_handle); + SDL_UnloadObject(library_handle); +} + +bool platform_load_gl(const char* name) +{ + if(SDL_GL_LoadLibrary(name) != 0) + { + log_error("platform:load_gl", "Failed to load GL'%s', SDL : (%s)", name, SDL_GetError()); + return false; + } + else + { + log_message("OpenGL loaded"); + } + return true; +} + +void platform_unload_gl(void) +{ + SDL_GL_UnloadLibrary(); + log_message("OpenGL unloaded"); +} + +void* platform_load_function_gl(const char* func_name) +{ + void* func_ptr = SDL_GL_GetProcAddress(func_name); + if(!func_ptr) log_error("platform:load_function_gl", "Failed to load GL function '%s' from library, SDL : (%s)", func_name, SDL_GetError()); + return func_ptr; +} diff --git a/src/platform.h b/src/platform.h index 5d15e10..1d562e7 100644 --- a/src/platform.h +++ b/src/platform.h @@ -1,7 +1,7 @@ #ifndef PLATFORM_H #define PLATFORM_H -#include "num_types.h" +#include "common.h" enum Video_Drivers_Linux { @@ -10,14 +10,6 @@ enum Video_Drivers_Linux VD_DUMMY }; -// Function Pointer decls -typedef void (*Keyboard_Event_Func) (int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); -typedef void (*Mousebutton_Event_Func) (int button, int state, int x, int y, int8 num_clicks); -typedef void (*Mousemotion_Event_Func) (int x, int y, int xrel, int yrel); -typedef void (*Mousewheel_Event_Func) (int x, int y); -typedef void (*Windowresize_Event_Func) (int x, int y); -typedef void (*Textinput_Event_Func) (const char* text); - // Window Related functions struct Window; @@ -59,5 +51,11 @@ void platform_clipboard_text_set(const char* text); char* platform_clipboard_text_get(void); int platform_key_from_name(const char* key_name); const char* platform_key_name_get(int key); +void* platform_load_library(const char* name); +void platform_unload_library(void* library_handle); +void* platform_load_function(void* library_handle, const char* func_name); +bool platform_load_gl(const char* name); +void platform_unload_gl(void); +void* platform_load_function_gl(const char* func_name); #endif diff --git a/src/renderer.c b/src/renderer.c index 7ec8955..9d4d042 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -14,12 +14,12 @@ #include "transform.h" #include "game.h" #include "gui.h" -#include "config_vars.h" #include "hashmap.h" #include "geometry.h" #include "material.h" #include "editor.h" #include "variant.h" +#include "common.h" #include #include @@ -46,7 +46,7 @@ void renderer_init(void) glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); - platform_windowresize_callback_set(on_framebuffer_size_change); + platform->windowresize_callback_set(on_framebuffer_size_change); gui_init(); /* Quad geometry for final render */ @@ -81,7 +81,7 @@ void renderer_init(void) int width = -1, height = -1; struct Game_State* game_state = game_state_get(); - window_get_size(game_state->window, &width, &height); + platform->window.get_size(game_state->window, &width, &height); def_albedo_tex = texture_create("def_albedo_texture", TU_DIFFUSE, width, height, @@ -353,7 +353,7 @@ void renderer_draw(struct Entity* active_viewer) /* Final Render */ int width, height; struct Game_State* game_state = game_state_get(); - window_get_size(game_state->window, &width, &height); + platform->window.get_size(game_state->window, &width, &height); glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); shader_bind(composition_shader); @@ -365,7 +365,7 @@ void renderer_draw(struct Entity* active_viewer) shader_unbind(); /* Debug Render */ - struct Hashmap* cvars = config_vars_get(); + struct Hashmap* cvars = platform->config.get(); if(hashmap_bool_get(cvars, "debug_draw_enabled")) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -449,13 +449,13 @@ int renderer_check_glerror(const char* context) void renderer_debug_draw_enabled(bool enabled) { - struct Hashmap* cvars = config_vars_get(); + struct Hashmap* cvars = platform->config.get(); hashmap_bool_set(cvars, "debug_draw_enabled", enabled); } void renderer_settings_get(struct Render_Settings* settings) { - struct Hashmap* cvars = config_vars_get(); + struct Hashmap* cvars = platform->config.get(); settings->fog.mode = hashmap_int_get(cvars, "fog_mode"); settings->fog.density = hashmap_float_get(cvars, "fog_density"); settings->fog.start_dist = hashmap_float_get(cvars, "fog_start_dist"); @@ -469,7 +469,7 @@ void renderer_settings_get(struct Render_Settings* settings) void renderer_settings_set(const struct Render_Settings* settings) { - struct Hashmap* cvars = config_vars_get(); + struct Hashmap* cvars = platform->config.get(); hashmap_int_set(cvars, "fog_mode", settings->fog.mode); hashmap_float_set(cvars, "fog_density", settings->fog.density); hashmap_float_set(cvars, "fog_start_dist", settings->fog.start_dist); diff --git a/src/scene.c b/src/scene.c index 4b60fbb..0adfeab 100644 --- a/src/scene.c +++ b/src/scene.c @@ -3,7 +3,7 @@ #include "entity.h" #include "log.h" #include "transform.h" -#include "file_io.h" +#include "common.h" #include #include @@ -125,7 +125,7 @@ struct Entity* scene_get_parent(struct Entity* entity) bool scene_load(const char* filename, int directory_type) { bool success = false; - FILE* entity_file = io_file_open(directory_type, filename, "r"); + FILE* entity_file = platform->file.open(directory_type, filename, "r"); if(!entity_file) { log_error("scene:load", "Failed to open scenefile %s for writing", filename); diff --git a/src/shader.c b/src/shader.c index 77c9a94..52638f0 100644 --- a/src/shader.c +++ b/src/shader.c @@ -1,5 +1,4 @@ #include "shader.h" -#include "file_io.h" #include "array.h" #include "num_types.h" #include "string_utils.h" @@ -7,6 +6,7 @@ #include "renderer.h" #include "texture.h" #include "gl_load.h" +#include "common.h" #include #include @@ -56,7 +56,7 @@ char* run_preprocessor(char* shader_text) { char* path = str_new("shaders/"); path = str_concat(path, filename); - char* file = io_file_read(DT_INSTALL, path, "r", NULL); + char* file = platform->file.read(DT_INSTALL, path, "r", NULL); char* shader_copy = str_new(shader_text); char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2)); if(temp) @@ -96,8 +96,8 @@ int shader_create(const char* vert_shader_name, const char* frag_shader_name) GLuint vert_shader = glCreateShader(GL_VERTEX_SHADER); GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER); - char* vert_source = io_file_read(DT_INSTALL, vs_path, "r", NULL); - char* frag_source = io_file_read(DT_INSTALL, fs_path, "r", NULL); + char* vert_source = platform->file.read(DT_INSTALL, vs_path, "r", NULL); + char* frag_source = platform->file.read(DT_INSTALL, fs_path, "r", NULL); assert(vert_source != NULL); assert(frag_source != NULL); diff --git a/src/sound.c b/src/sound.c index 9bd7b33..b2ab199 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1,7 +1,5 @@ #include "sound.h" #include "log.h" -#include "transform.h" -#include "entity.h" #include "array.h" #include "string_utils.h" #include "file_io.h" @@ -15,7 +13,6 @@ struct Sound_State { - int listener_entity; ALCdevice* device; ALCcontext* context; float volume; @@ -23,7 +20,6 @@ struct Sound_State static struct Sound_State sound_state = { - .listener_entity = -1, .device = NULL, .context = NULL, .volume = 0.f @@ -32,7 +28,6 @@ static struct Sound_State sound_state = bool sound_init(void) { bool success = false; - sound_state.device = alcOpenDevice(NULL); if(!sound_state.device) { @@ -51,7 +46,6 @@ bool sound_init(void) log_message("Opened %s", alcGetString(sound_state.device, ALC_DEVICE_SPECIFIER)); /* Set default listener values */ - sound_state.listener_entity = -1; sound_state.volume = 1.f; float orientation[] = { @@ -66,67 +60,36 @@ bool sound_init(void) return success; } -void sound_listener_set(int listener_entity) -{ - assert(listener_entity > -1); - if(sound_state.listener_entity != -1) - { - struct Entity* current_listener = entity_get(sound_state.listener_entity); - current_listener->is_listener = false; - } - - sound_state.listener_entity = listener_entity; - struct Entity* entity = entity_get(listener_entity); - entity->is_listener = true; - sound_listener_update(); -} - -void sound_listener_update(void) -{ - if(sound_state.listener_entity == -1) return; - struct Entity* entity = entity_get(sound_state.listener_entity); - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - vec3 abs_forward = {0.f, 0.f, -1.f}; - - transform_get_absolute_pos(entity, &abs_pos); - transform_get_absolute_up(entity, &abs_up); - transform_get_absolute_forward(entity, &abs_forward); +void sound_listener_update(float apos_x, float apos_y, float apos_z, + float afwd_x, float afwd_y, float afwd_z, + float aup_x, float aup_y, float aup_z) +{ float orientation[] = { - abs_forward.x, abs_forward.y, abs_forward.z, - abs_up.x, abs_up.y, abs_up.z + afwd_x, afwd_y, afwd_z, + aup_x, aup_y, aup_z }; - al_check(alListener3f(AL_POSITION, abs_pos.x, abs_pos.y, abs_pos.z)) + al_check(alListener3f(AL_POSITION, apos_x, apos_y, apos_z)) al_check(alListenerfv(AL_ORIENTATION, orientation)) } -int sound_listener_get(void) -{ - return sound_state.listener_entity; -} - void sound_volume_set(float volume) { if(volume < 0.f) volume = 0.f; al_check(alListenerf(AL_GAIN, volume)) } -void sound_source_destroy(struct Entity* entity) +void sound_source_destroy(uint source_handle, uint* attached_buffers, uint num_buffers) { - assert(entity && entity->type == ET_SOUND_SOURCE); - struct Sound_Source* source = &entity->sound_source; - if(!source->active) return; - if(alIsBuffer(source->al_buffer_handle) == AL_TRUE) - { - sound_source_stop(entity); - al_check(alSourcei(source->al_source_handle, AL_BUFFER, 0)) - al_check(alDeleteBuffers(1, &source->al_buffer_handle)) - } - if(alIsSource(source->al_source_handle) == AL_TRUE) al_check(alDeleteSources(1, &source->al_source_handle)) - source->al_buffer_handle = 0; - source->al_source_handle = 0; - source->active = false; + for(int i = 0; i < (int)num_buffers; i++) + { + if(alIsBuffer(attached_buffers[i]) == AL_TRUE) + { + al_check(alSourcei(source_handle, AL_BUFFER, i)) + al_check(alDeleteBuffers(1, &attached_buffers[i])) + } + } + if(alIsSource(source_handle) == AL_TRUE) al_check(alDeleteSources(1, &source_handle)) } void sound_cleanup(void) @@ -137,7 +100,6 @@ void sound_cleanup(void) sound_state.context = NULL; sound_state.device = NULL; sound_state.volume = 0.f; - sound_state.listener_entity = -1; } void sound_error_check(const char* file, unsigned int line, const char* expression) @@ -158,71 +120,55 @@ void sound_error_check(const char* file, unsigned int line, const char* expressi } } -void sound_source_create(struct Entity* entity, bool relative) +void sound_source_create(bool relative, uint num_buffers, uint* out_handle, uint* out_buffer_handles) { - assert(entity && entity->type == ET_SOUND_SOURCE); - struct Sound_Source* source = &entity->sound_source; - source->active = true; - al_check(alGenSources(1, &source->al_source_handle)) - al_check(alGenBuffers(1, &source->al_buffer_handle)) - sound_source_volume_set(entity, 1.f); + al_check(alGenSources(1, out_handle)) + al_check(alGenBuffers((int)num_buffers, out_buffer_handles)) + sound_source_volume_set(*out_handle, 1.f); if(relative) - sound_source_relative_set(entity, true); - else - sound_source_update(entity); + sound_source_relative_set(*out_handle, true); } -void sound_source_update(struct Entity* entity) +void sound_source_update(uint source_handle, + float apos_x, float apos_y, float apos_z, + float afwd_x, float afwd_y, float afwd_z, + float aup_x, float aup_y, float aup_z) { - assert(entity && entity->type == ET_SOUND_SOURCE); - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - vec3 abs_forward = {0.f, 0.f, -1.f}; - - transform_get_absolute_pos(entity, &abs_pos); - transform_get_absolute_up(entity, &abs_up); - transform_get_absolute_forward(entity, &abs_forward); float orientation[] = { - abs_forward.x, abs_forward.y, abs_forward.z, - abs_up.x, abs_up.y, abs_up.z + afwd_x, afwd_y, afwd_z, + aup_x, aup_y, aup_z }; - al_check(alSource3f(entity->sound_source.al_source_handle, AL_POSITION, abs_pos.x, abs_pos.y, abs_pos.z)) - al_check(alSourcefv(entity->sound_source.al_source_handle, AL_ORIENTATION, orientation)) + al_check(alSource3f(source_handle, AL_POSITION, apos_x, apos_y, apos_z)) + al_check(alSourcefv(source_handle, AL_ORIENTATION, orientation)) } -void sound_source_volume_set(struct Entity* entity, float volume) +void sound_source_volume_set(uint source_handle, float volume) { - assert(entity && entity->type == ET_SOUND_SOURCE); if(volume < 0.f) volume = 0.f; - al_check(alSourcef(entity->sound_source.al_source_handle, AL_GAIN, volume)) + al_check(alSourcef(source_handle, AL_GAIN, volume)) } -void sound_source_pitch_set(struct Entity* entity, float pitch) +void sound_source_pitch_set(uint source_handle, float pitch) { - assert(entity && entity->type == ET_SOUND_SOURCE); if(pitch < 0.f) pitch = 0.f; - al_check(alSourcef(entity->sound_source.al_source_handle, AL_PITCH, pitch)) + al_check(alSourcef(source_handle, AL_PITCH, pitch)) } -void sound_source_loop_set(struct Entity* entity, bool loop) +void sound_source_loop_set(uint source_handle, bool loop) { - assert(entity && entity->type == ET_SOUND_SOURCE); loop = loop ? AL_TRUE : AL_FALSE; - al_check(alSourcei(entity->sound_source.al_source_handle, AL_LOOPING, loop)) + al_check(alSourcei(source_handle, AL_LOOPING, loop)) } -void sound_source_relative_set(struct Entity* entity, bool relative) +void sound_source_relative_set(uint source_handle, bool relative) { - assert(entity && entity->type == ET_SOUND_SOURCE); relative = relative ? AL_TRUE : AL_FALSE; - al_check(alSourcei(entity->sound_source.al_source_handle, AL_SOURCE_RELATIVE, relative)); - entity->sound_source.relative = relative; + al_check(alSourcei(source_handle, AL_SOURCE_RELATIVE, relative)); } -void sound_source_load_wav(struct Entity* entity, const char* file_name) +void sound_source_load_wav(uint source_handle, uint buffer_handle, const char* file_name) { - assert(entity && entity->type == ET_SOUND_SOURCE); if(!file_name) { log_error("sound_source:load_wav", "No file name given"); @@ -278,32 +224,27 @@ void sound_source_load_wav(struct Entity* entity, const char* file_name) return; } - struct Sound_Source* source = &entity->sound_source; - al_check(alBufferData(source->al_buffer_handle, format, wav_data, wav_data_len, wav_spec.freq)) - al_check(alSourcei(source->al_source_handle, AL_BUFFER, source->al_buffer_handle)) + al_check(alBufferData(buffer_handle, format, wav_data, wav_data_len, wav_spec.freq)) + al_check(alSourcei(source_handle, AL_BUFFER, buffer_handle)) SDL_FreeWAV(wav_data); } -void sound_source_play(struct Entity* entity) +void sound_source_play(uint source_handle) { - assert(entity && entity->type == ET_SOUND_SOURCE); - al_check(alSourcePlay(entity->sound_source.al_source_handle)) + al_check(alSourcePlay(source_handle)) } -void sound_source_pause(struct Entity* entity) +void sound_source_pause(uint source_handle) { - assert(entity && entity->type == ET_SOUND_SOURCE); - al_check(alSourcePause(entity->sound_source.al_source_handle)) + al_check(alSourcePause(source_handle)) } -void sound_source_rewind(struct Entity* entity) +void sound_source_rewind(uint source_handle) { - assert(entity && entity->type == ET_SOUND_SOURCE); - al_check(alSourceRewind(entity->sound_source.al_source_handle)) + al_check(alSourceRewind(source_handle)) } -void sound_source_stop(struct Entity* entity) +void sound_source_stop(uint source_handle) { - assert(entity && entity->type == ET_SOUND_SOURCE); - al_check(alSourceStop(entity->sound_source.al_source_handle)) + al_check(alSourceStop(source_handle)) } diff --git a/src/sound.h b/src/sound.h index 47cb5b9..3cd58a7 100644 --- a/src/sound.h +++ b/src/sound.h @@ -9,28 +9,29 @@ #define al_check(expr) expr; #endif -struct Entity; - bool sound_init(void); void sound_cleanup(void); void sound_volume_set(float volume); void sound_error_check(const char* file, unsigned int line, const char* expression); -void sound_listener_set(int entity); -int sound_listener_get(void); -void sound_listener_update(void); +void sound_listener_update(float apos_x, float apos_y, float apos_z, + float afwd_x, float afwd_y, float afwd_z, + float aup_x, float aup_y, float aup_z); -void sound_source_create(struct Entity* entity, bool relative); -void sound_source_destroy(struct Entity* entity); -void sound_source_update(struct Entity* entity); -void sound_source_volume_set(struct Entity* entity, float volume); -void sound_source_pitch_set(struct Entity* entity, float pitch); -void sound_source_load_wav(struct Entity* entity, const char* file_name); -void sound_source_loop_set(struct Entity* entity, bool loop); -void sound_source_relative_set(struct Entity* entity, bool relative); -void sound_source_play(struct Entity* entity); -void sound_source_pause(struct Entity* entity); -void sound_source_rewind(struct Entity* entity); -void sound_source_stop(struct Entity* entity); +void sound_source_update(uint source_handle, + float apos_x, float apos_y, float apos_z, + float afwd_x, float afwd_y, float afwd_z, + float aup_x, float aup_y, float aup_z); +void sound_source_create(bool relative, uint num_buffers, uint* out_handle, uint* out_buffer_handles); +void sound_source_destroy(uint source_handle, uint* attached_buffers, uint num_buffers); +void sound_source_volume_set(uint source_handle, float volume); +void sound_source_pitch_set(uint source_handle, float pitch); +void sound_source_load_wav(uint source_handle, uint buffer_handle, const char* file_name); +void sound_source_loop_set(uint source_handle, bool loop); +void sound_source_relative_set(uint source_handle, bool relative); +void sound_source_play(uint source_handle); +void sound_source_pause(uint source_handle); +void sound_source_rewind(uint source_handle); +void sound_source_stop(uint source_handle); #endif diff --git a/src/texture.c b/src/texture.c index 16a0538..36fdd62 100644 --- a/src/texture.c +++ b/src/texture.c @@ -1,11 +1,11 @@ #include "texture.h" #include "array.h" -#include "file_io.h" #include "string_utils.h" #include "log.h" #include "num_types.h" #include "renderer.h" #include "gl_load.h" +#include "common.h" #include #include @@ -68,7 +68,7 @@ int texture_create_from_file(const char* filename, int texture_unit) } /* If texture not already loaded then try to load it */ char* full_path = str_new("textures/%s", filename); - FILE* file = io_file_open(DT_INSTALL, full_path, "rb"); + FILE* file = platform->file.open(DT_INSTALL, full_path, "rb"); int img_load_success = -1; if(file) diff --git a/src/variant.c b/src/variant.c index 0be7110..56d1a92 100644 --- a/src/variant.c +++ b/src/variant.c @@ -29,6 +29,13 @@ void variant_assign_int(struct Variant* variant, const int value) variant->val_int = value; } +void variant_assign_uint(struct Variant* variant, const uint value) +{ + if(variant->type != VT_UINT) variant_free(variant); + variant->type = VT_UINT; + variant->val_uint = value; +} + void variant_assign_double(struct Variant* variant, const double value) { if(variant->type != VT_DOUBLE) variant_free(variant); @@ -159,6 +166,7 @@ void variant_copy(struct Variant* to, const struct Variant* from) { case VT_BOOL: variant_assign_bool(to, from->val_bool); break; case VT_INT: variant_assign_int(to, from->val_int); break; + case VT_UINT: variant_assign_uint(to, from->val_uint); break; case VT_FLOAT: variant_assign_float(to, from->val_float); break; case VT_DOUBLE: variant_assign_double(to, from->val_double); break; case VT_VEC2: variant_assign_vec2(to, &from->val_vec2); break; @@ -179,6 +187,7 @@ void variant_to_str(const struct Variant* variant, char* str, int len) { case VT_BOOL: snprintf(str, len, "%s", variant->val_bool ? "true" : "false"); break; case VT_INT: snprintf(str, len, "%d", variant->val_int); break; + case VT_UINT: snprintf(str, len, "%d", variant->val_uint); break; case VT_FLOAT: snprintf(str, len, "%.4f", variant->val_float); break; case VT_DOUBLE: snprintf(str, len, "%.4f", variant->val_double); break; case VT_VEC2: snprintf(str, len, "%.3f %.3f", variant->val_vec2.x, variant->val_vec2.y); break; @@ -219,6 +228,13 @@ void variant_from_str(struct Variant* variant, const char* str, int variant_type variant_assign_int(variant, int_val); } break; + case VT_UINT: + { + uint uint_val = 0; + if(sscanf(str, "%d", &uint_val) == 1) + variant_assign_uint(variant, uint_val); + } + break; case VT_FLOAT: { float float_val = -1; @@ -278,6 +294,7 @@ void variant_copy_out(void* to, const struct Variant* from) { case VT_BOOL: *(bool*)to = from->val_bool; break; case VT_INT: *(int*)to = from->val_int; break; + case VT_UINT: *(uint*)to = from->val_uint; break; case VT_FLOAT: *(float*)to = from->val_float; break; case VT_DOUBLE: *(double*)to = from->val_double; break; case VT_VEC2: vec2_assign((vec2*)to, &from->val_vec2); break; diff --git a/src/variant.h b/src/variant.h index f29ca81..de3e8b0 100644 --- a/src/variant.h +++ b/src/variant.h @@ -11,6 +11,7 @@ enum Variant_Type VT_NONE = 0, VT_BOOL, VT_INT, + VT_UINT, VT_FLOAT, VT_DOUBLE, VT_STR, @@ -29,6 +30,7 @@ struct Variant union { int val_int; + uint val_uint; bool val_bool; float val_float; double val_double; @@ -45,6 +47,7 @@ struct Variant void variant_init_empty(struct Variant* variant); void variant_assign_float(struct Variant* variant, const float value); void variant_assign_int(struct Variant* variant, const int value); +void variant_assign_uint(struct Variant* variant, const uint value); void variant_assign_double(struct Variant* variant, const double value); void variant_assign_bool(struct Variant* variant, const bool value); void variant_assign_str(struct Variant* variant, const char* value);