Separated Game and Game Library code into executable and reloadable shared library

dev
shariq 8 years ago
parent 132e49f434
commit 16b3293b41
  1. 5
      README.md
  2. 1
      assets/keybindings.cfg
  3. 54
      build/linux/makefile
  4. 131
      src/common.h
  5. 8
      src/editor.c
  6. 56
      src/entity.c
  7. 6
      src/entity.h
  8. 8
      src/file_io.h
  9. 85
      src/game.c
  10. 4
      src/game.h
  11. 4
      src/geometry.c
  12. 31
      src/gl_load.c
  13. 5
      src/gl_load.h
  14. 15
      src/gui.c
  15. 41
      src/input.c
  16. 21
      src/log.c
  17. 6
      src/log.h
  18. 150
      src/main.c
  19. 63
      src/platform.c
  20. 16
      src/platform.h
  21. 16
      src/renderer.c
  22. 4
      src/scene.c
  23. 8
      src/shader.c
  24. 153
      src/sound.c
  25. 35
      src/sound.h
  26. 4
      src/texture.c
  27. 17
      src/variant.c
  28. 3
      src/variant.h

@ -149,6 +149,9 @@
- ## TODO - ## 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 - Finish entity loading from file then move on to 2D rendering
- First class 2d rendering - First class 2d rendering
- Sprite batching (XNA like) - Sprite batching (XNA like)
@ -177,7 +180,6 @@
- Better handling incase assets folder is not found? - Better handling incase assets folder is not found?
- Write entity to/from file - Write entity to/from file
- Ogg format loading and playback - Ogg format loading and playback
- Stick with OpenAL or switch to SoLoud + SDL for sound?
- Sound streaming - Sound streaming
- Implment missing sound source properties (inner/outer cone, getting sound source data) - Implment missing sound source properties (inner/outer cone, getting sound source data)
- Ingame console and console commands etc - Ingame console and console commands etc
@ -296,3 +298,4 @@
* Fix camera acting all weird when right click is held * Fix camera acting all weird when right click is held
* Fix README to conform with markdown syntax * Fix README to conform with markdown syntax
* Added video driver selection to make game launch under wayland or x11 on linux. * 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.

@ -12,3 +12,4 @@ Turn_Down : K
Editor_Toggle : F1 Editor_Toggle : F1
Window_Fullscreen : F11 Window_Fullscreen : F11
Window_Maximize : F12 Window_Maximize : F12
Reload_Game_Lib : Left Ctrl-Left Shift-R

@ -4,38 +4,55 @@ SRC_DIR = ../../src
INCLUDE_DIR = ../../include INCLUDE_DIR = ../../include
DIST_DIR = ../../bin/linux DIST_DIR = ../../bin/linux
BUILD_TYPE = release BUILD_TYPE = release
SRCS = $(patsubst $(SRC_DIR)/%.c, %.c, $(wildcard ../../src/*.c)) CFLAGS = -Wall -I$(INCLUDE_DIR) -DUSE_GLAD -std=c99
OBJS_RELEASE = $(patsubst %.c,.release/%.o,$(SRCS)) CFLAGS_GAME = $(CFLAGS) -DGAME $(shell pkg-config --cflags-only-other sdl2 openal)
OBJS_DEBUG = $(patsubst %.c,.debug/%.o,$(SRCS)) CFLAGS_GAME_LIB = $(CFLAGS) -DGAME_LIB
CFLAGS = -Wall -I$(INCLUDE_DIR) -DUSE_GLAD -std=c99 $(shell pkg-config --cflags-only-other sdl2 openal)
CFLAGS_DEBUG = -g -DGL_DEBUG_CONTEXT -DAL_DEBUG CFLAGS_DEBUG = -g -DGL_DEBUG_CONTEXT -DAL_DEBUG
CFLAGS_RELEASE = -O3 -ffast-math 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 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 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: BUILD_TYPE = release
release: CFLAGS += $(CFLAGS_RELEASE) release: CFLAGS_GAME += $(CFLAGS_RELEASE)
release: pre_build $(OBJS_RELEASE) post_build release: pre_build $(OBJS_RELEASE_GAME) post_build
-@echo -e "\e[34mLINKING\e[0m Release 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)" -@echo -e "\e[32mDONE\e[0m building $(PROJECT_NAME)"
debug: BUILD_TYPE = debug debug: BUILD_TYPE = debug
debug: CFLAGS += $(CFLAGS_DEBUG) debug: CFLAGS_GAME += $(CFLAGS_DEBUG)
debug: pre_build $(OBJS_DEBUG) post_build debug: pre_build $(OBJS_DEBUG_GAME) post_build
-@echo -e "\e[34mLINKING\e[0m Debug 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)" -@echo -e "\e[32mDONE\e[0m building $(PROJECT_NAME)"
.release/%.o: $(SRC_DIR)/%.c .release/%.o: $(SRC_DIR)/%.c
-@echo -e "\e[96mCompiling $<\e[0m" -@echo -e "\e[96mCompiling $<\e[0m"
-@$(CC) $(CFLAGS) -c $< -o $@ -@$(CC) $(CFLAGS_GAME) -c $< -o $@
.debug/%.o: $(SRC_DIR)/%.c .debug/%.o: $(SRC_DIR)/%.c
-@echo -e "\e[96mCompiling $<\e[0m" -@echo -e "\e[96mCompiling $<\e[0m"
-@$(CC) $(CFLAGS) -c $< -o $@ -@$(CC) $(CFLAGS_GAME) -c $< -o $@
pre_build: pre_build:
-@mkdir -p .debug .release -@mkdir -p .debug .release
@ -68,6 +85,13 @@ upload_itch: dist
clean: clean:
-@echo -e "\e[31m" -@echo -e "\e[31m"
-rm -f $(PROJECT_NAME) -rm -f $(PROJECT_NAME)
-rm -rf .release -rm -rf .release/*.o
-rm -rf .debug -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" -@echo -e "\e[0m"

@ -0,0 +1,131 @@
#ifndef COMMON_H
#define COMMON_H
#include <stdio.h>
#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

@ -17,10 +17,8 @@
#include "array.h" #include "array.h"
#include "variant.h" #include "variant.h"
#include "num_types.h" #include "num_types.h"
#include "file_io.h"
#include "config_vars.h"
#include "string_utils.h" #include "string_utils.h"
#include "platform.h" #include "common.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -152,7 +150,7 @@ void editor_update(float dt)
struct Gui_State* gui_state = gui_state_get(); struct Gui_State* gui_state = gui_state_get();
struct nk_context* context = &gui_state->context; struct nk_context* context = &gui_state->context;
int win_width = 0, win_height = 0; 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; int half_width = win_width / 2, half_height = win_height / 2;
static int window_flags = NK_WINDOW_BORDER | static int window_flags = NK_WINDOW_BORDER |
NK_WINDOW_CLOSABLE | NK_WINDOW_CLOSABLE |
@ -189,7 +187,7 @@ void editor_update(float dt)
if(nk_button_label(context, "Render Settings")) if(nk_button_label(context, "Render Settings"))
editor_state.renderer_settings_window = !editor_state.renderer_settings_window; editor_state.renderer_settings_window = !editor_state.renderer_settings_window;
if(nk_button_label(context, "Save config")) 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_spacing(context, 1);
nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps);
nk_group_end(context); nk_group_end(context);

@ -6,11 +6,10 @@
#include "camera.h" #include "camera.h"
#include "light.h" #include "light.h"
#include "model.h" #include "model.h"
#include "sound.h"
#include "material.h" #include "material.h"
#include "geometry.h" #include "geometry.h"
#include "variant.h" #include "variant.h"
#include "file_io.h" #include "common.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -51,8 +50,14 @@ void entity_remove(int index)
{ {
case ET_CAMERA: camera_destroy(entity); break; case ET_CAMERA: camera_destroy(entity); break;
case ET_LIGHT: light_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_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; case ET_ROOT: break;
default: log_error("entity:remove", "Invalid entity type"); break; default: log_error("entity:remove", "Invalid entity type"); break;
}; };
@ -142,11 +147,37 @@ void entity_post_update(void)
if(entity->transform.is_modified) if(entity->transform.is_modified)
{ {
if(entity->type == ET_CAMERA) if(entity->type == ET_CAMERA)
{
camera_update_view(entity); camera_update_view(entity);
}
else if(entity->type == ET_SOUND_SOURCE) else if(entity->type == ET_SOUND_SOURCE)
sound_source_update(entity); {
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);
if(entity->is_listener) sound_listener_update(); 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 entity_save(struct Entity* entity, const char* filename, int directory_type)
{ {
bool success = false; 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) if(!entity_file)
{ {
log_error("entity:save", "Failed to open entity file %s for writing"); 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) 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) if(!entity_file)
{ {
log_error("entity:load", "Failed to open entity file %s for writing", filename); 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_from_str(&var_value, value_str, VT_BOOL);
variant_copy_out(&entity.sound_source.relative, &var_value); 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); 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); quat_assign(&new_entity->transform.rotation, &entity.transform.rotation);
transform_scale(new_entity, &entity.transform.scale); transform_scale(new_entity, &entity.transform.scale);
if(entity.is_listener) sound_listener_set(new_entity->id);
if(entity.renderable) new_entity->renderable = true; if(entity.renderable) new_entity->renderable = true;
switch(new_entity->type) switch(new_entity->type)
@ -497,7 +532,10 @@ struct Entity* entity_load(const char* filename, int directory_type)
light_add(new_entity); light_add(new_entity);
break; break;
case ET_SOUND_SOURCE: 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; break;
}; };

@ -5,6 +5,7 @@
#include "num_types.h" #include "num_types.h"
#define MAX_ENTITY_NAME_LEN 128 #define MAX_ENTITY_NAME_LEN 128
#define MAX_SOUND_SOURCE_BUFFERS 5
struct Material_Param; struct Material_Param;
@ -51,8 +52,9 @@ struct Sound_Source
{ {
bool active; bool active;
bool relative; bool relative;
uint al_source_handle; uint source_handle;
uint al_buffer_handle; uint buffer_handles[MAX_SOUND_SOURCE_BUFFERS];
uint num_attached_buffers;
}; };
struct Camera struct Camera

@ -1,13 +1,7 @@
#ifndef FILE_IO_H #ifndef FILE_IO_H
#define FILE_IO_H #define FILE_IO_H
#include <stdio.h> #include "common.h"
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 */
};
void io_file_init(const char* install_dir, const char* user_dir); 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); char* io_file_read(const int directory_type, const char* path, const char* mode, long* file_size);

@ -2,13 +2,12 @@
#include <stddef.h> #include <stddef.h>
#include <time.h> #include <time.h>
#include <limits.h> #include <limits.h>
#include <string.h>
#include "game.h" #include "game.h"
#include "platform.h"
#include "input.h" #include "input.h"
#include "renderer.h" #include "renderer.h"
#include "log.h" #include "log.h"
#include "file_io.h"
#include "shader.h" #include "shader.h"
#include "entity.h" #include "entity.h"
#include "geometry.h" #include "geometry.h"
@ -24,11 +23,11 @@
#include "light.h" #include "light.h"
#include "gl_load.h" #include "gl_load.h"
#include "gui.h" #include "gui.h"
#include "sound.h"
#include "editor.h" #include "editor.h"
#include "config_vars.h" #include "config_vars.h"
#include "hashmap.h" #include "hashmap.h"
#include "variant.h" #include "variant.h"
#include "common.h"
#define UNUSED(a) (void)a #define UNUSED(a) (void)a
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
@ -38,7 +37,7 @@
#define MAX_FRAME_TIME 0.5f #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 update(float dt, bool* window_should_close);
static void render(void); static void render(void);
static void debug(float dt); static void debug(float dt);
@ -46,9 +45,18 @@ static void debug_gui(float dt);
static void scene_setup(void); static void scene_setup(void);
static struct Game_State* game_state = NULL; 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)); game_state = malloc(sizeof(*game_state));
if(!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" */ /* TODO: Decouple systems' init/cleanup from game, they should exist and run even if there's no "game" */
/* Init systems */ /* 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(); input_init();
sound_init();
shader_init(); shader_init();
texture_init(); texture_init();
framebuffer_init(); framebuffer_init();
@ -96,7 +113,6 @@ void scene_setup(void)
camera_create(player, render_width, render_height); camera_create(player, render_width, render_height);
camera_attach_fbo(player, render_width, render_height, 1, 1, 1); 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); 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 }; vec4 color = {1.f, 1.f, 1.f, 1.f };
struct Entity* new_ent = scene_add_new("Model_Entity", ET_STATIC_MESH); 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); transform_scale(new_ent, &scale);
struct Entity* sound_ent = scene_add_as_child("Sound_ENT", ET_SOUND_SOURCE, new_ent->id); struct Entity* sound_ent = scene_add_as_child("Sound_ENT", ET_SOUND_SOURCE, new_ent->id);
sound_source_create(sound_ent, false); struct Sound_Source* sound_source = &sound_ent->sound_source;
sound_source_load_wav(sound_ent, "BigExplosion.wav"); 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_relative_set(source, true);
sound_source_volume_set(sound_ent, 1.f); platform->sound.source_volume_set(sound_source->source_handle, 1.f);
sound_source_loop_set(sound_ent, true); platform->sound.source_loop_set(sound_source->source_handle, true);
sound_source_play(sound_ent); platform->sound.source_play(sound_source->source_handle);
int parent_node = new_ent->id; int parent_node = new_ent->id;
int num_suz = 50; int num_suz = 50;
@ -220,12 +239,12 @@ void debug(float dt)
turn_up_down = -cursor_ud * turn_speed * dt * scale; turn_up_down = -cursor_ud * turn_speed * dt * scale;
turn_left_right = cursor_lr * 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 else
{ {
input_mouse_mode_set(MM_NORMAL); 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_up_down *= dt;
turn_left_right *= dt; turn_left_right *= dt;
} }
@ -308,42 +327,43 @@ void debug(float dt)
transform_translate(model, &amount, TS_LOCAL); transform_translate(model, &amount, TS_LOCAL);
} }
/* struct Entity* model = scene_find("Light_Ent"); */ struct Entity* model = scene_find("Model_Entity");
/* vec3 x_axis = {0, 1, 0}; */ vec3 x_axis = {0, 1, 0};
/* transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD); */ transform_rotate(model, &x_axis, 25.f * dt, TS_WORLD);
/* vec3 amount = {0, 0, -5 * dt}; */ vec3 amount = {0, 0, -5 * dt};
/* transform_translate(model, &amount, TS_LOCAL); */ 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; bool should_window_close = 0;
while(!should_window_close) 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; float delta_time = (float)(curr_time - last_time) / 1000.f;
last_time = curr_time; 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 */ 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(); gui_input_begin();
platform_poll_events(&should_window_close); platform->poll_events(&should_window_close);
gui_input_end(); gui_input_end();
update(delta_time, &should_window_close); update(delta_time, &should_window_close);
render(); render();
window_swap_buffers(game_state->window); platform->window.swap_buffers(game_state->window);
entity_post_update(); entity_post_update();
} }
return 1; return true;
} }
void update(float dt, bool* window_should_close) void update(float dt, bool* window_should_close)
{ {
if(input_is_key_pressed(KEY_ESCAPE)) *window_should_close = true; 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("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_Fullscreen", KS_RELEASED)) platform->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_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(dt);
//debug_gui(dt); //debug_gui(dt);
@ -1576,20 +1596,23 @@ void game_cleanup(void)
light_cleanup(); light_cleanup();
input_cleanup(); input_cleanup();
renderer_cleanup(); renderer_cleanup();
io_file_cleanup();
framebuffer_cleanup(); framebuffer_cleanup();
texture_cleanup(); texture_cleanup();
shader_cleanup(); shader_cleanup();
sound_cleanup();
window_destroy(game_state->window);
gl_cleanup();
} }
free(game_state); free(game_state);
game_state = NULL; game_state = NULL;
} }
if(platform) free(platform);
} }
struct Game_State* game_state_get(void) struct Game_State* game_state_get(void)
{ {
return game_state; return game_state;
} }
void game_test(const char *str)
{
log_message("Func called!");
}

@ -4,6 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
struct Window; struct Window;
struct Platform_Api;
struct Game_State struct Game_State
{ {
@ -15,7 +16,8 @@ struct Game_State
struct Game_State* game_state_get(void); 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_cleanup(void);
void game_test(const char* str);
#endif #endif

@ -1,10 +1,10 @@
#include "geometry.h" #include "geometry.h"
#include "array.h" #include "array.h"
#include "string_utils.h" #include "string_utils.h"
#include "file_io.h"
#include "log.h" #include "log.h"
#include "renderer.h" #include "renderer.h"
#include "transform.h" #include "transform.h"
#include "common.h"
#include "gl_load.h" #include "gl_load.h"
#include <stdlib.h> #include <stdlib.h>
@ -214,7 +214,7 @@ static int load_from_file(struct Geometry* geometry, const char* filename)
int success = 1; int success = 1;
char* full_path = str_new("models/%s", filename); 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); free(full_path);
if(file) if(file)
{ {

@ -1,6 +1,6 @@
#include "gl_load.h" #include "gl_load.h"
#include "log.h" #include "log.h"
#include <SDL2/SDL.h> #include "common.h"
#ifndef USE_GLAD #ifndef USE_GLAD
@ -14,23 +14,23 @@ SYMMETRY_GL_LIST
int gl_load_library(void) int gl_load_library(void)
{ {
int success = 1; int success = 1;
if(SDL_GL_LoadLibrary(NULL) < 0) // if(SDL_GL_LoadLibrary(NULL) < 0)
{ // {
success = 0; // success = 0;
log_error("gl_load_library", "Failed to load GL library %s", SDL_GetError()); // log_error("gl_load_library", "Failed to load GL library %s", SDL_GetError());
} // }
else // else
{ // {
log_message("Loaded GL library"); // log_message("Loaded GL library");
} // }
return success; return success;
} }
int gl_load_extentions(void) bool gl_load_extentions(void)
{ {
int success = 1; bool success = true;
#ifdef USE_GLAD #ifdef USE_GLAD
if(!gladLoadGLLoader(&SDL_GL_GetProcAddress)) success = 0; if(!gladLoadGLLoader(platform->load_function_gl)) success = false;
#else #else
#define GLE(ret, name, ...) \ #define GLE(ret, name, ...) \
@ -45,8 +45,3 @@ int gl_load_extentions(void)
#endif #endif
return success; return success;
} }
void gl_cleanup(void)
{
SDL_GL_UnloadLibrary();
}

@ -2,7 +2,10 @@
#define GL_LOAD_H #define GL_LOAD_H
#ifdef USE_GLAD #ifdef USE_GLAD
#include <glad/glad.h> #include <glad/glad.h>
#include <stdbool.h>
#else #else
#include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengl.h>
@ -60,7 +63,7 @@ SYMMETRY_GL_LIST
#endif #endif
int gl_load_library(void); int gl_load_library(void);
int gl_load_extentions(void); bool gl_load_extentions(void);
void gl_cleanup(void); void gl_cleanup(void);
#endif #endif

@ -1,6 +1,5 @@
#define NK_IMPLEMENTATION #define NK_IMPLEMENTATION
#include "gui.h" #include "gui.h"
#include "platform.h"
#include "linmath.h" #include "linmath.h"
#include "log.h" #include "log.h"
#include "shader.h" #include "shader.h"
@ -8,8 +7,8 @@
#include "game.h" #include "game.h"
#include "input.h" #include "input.h"
#include "renderer.h" #include "renderer.h"
#include "file_io.h"
#include "string_utils.h" #include "string_utils.h"
#include "common.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -89,7 +88,7 @@ bool gui_init(void)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(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("Ubuntu-R.ttf", 14);
//gui_font_set("FiraSans-Regular.ttf", 14); //gui_font_set("FiraSans-Regular.ttf", 14);
gui_font_set("RobotoCondensed-Regular.ttf", 18); gui_font_set("RobotoCondensed-Regular.ttf", 18);
@ -133,8 +132,8 @@ void gui_render(enum nk_anti_aliasing AA)
mat4_identity(&gui_mat); mat4_identity(&gui_mat);
struct Game_State* game_state = game_state_get(); 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);
window_get_drawable_size(game_state->window, &display_width, &display_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); mat4_ortho(&gui_mat, 0, display_width, display_height, 0, -100, 100);
scale.x = (float)display_width/(float)width; 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) 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) if(text)
{ {
nk_textedit_paste(edit, text, nk_strlen(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; if (!str) return;
memcpy(str, text, (size_t)len); memcpy(str, text, (size_t)len);
str[len] = '\0'; str[len] = '\0';
platform_clipboard_text_set(str); platform->clipboard_text_set(str);
free(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; struct nk_font_atlas* atlas = &gui_state->atlas;
long size = 0; long size = 0;
char* font_file_name = str_new("fonts/%s", font_name); 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); free(font_file_name);
if(!font_data) if(!font_data)
{ {

@ -3,11 +3,10 @@
#include <string.h> #include <string.h>
#include "input.h" #include "input.h"
#include "array.h" #include "array.h"
#include "platform.h"
#include "log.h" #include "log.h"
#include "gui.h" #include "gui.h"
#include "file_io.h"
#include "string_utils.h" #include "string_utils.h"
#include "common.h"
struct Input_Map struct Input_Map
{ {
@ -26,10 +25,10 @@ static struct Input_Map* input_map_list = NULL;
void input_init(void) void input_init(void)
{ {
platform_keyboard_callback_set(&input_on_key); platform->keyboard_callback_set(&input_on_key);
platform_mousebutton_callback_set(&input_on_mousebutton); platform->mousebutton_callback_set(&input_on_mousebutton);
platform_mousemotion_callback_set(&input_on_mousemotion); platform->mousemotion_callback_set(&input_on_mousemotion);
platform_mousewheel_callback_set(&input_on_mousewheel); platform->mousewheel_callback_set(&input_on_mousewheel);
input_map_list = array_new(struct Input_Map); input_map_list = array_new(struct Input_Map);
if(!input_keybinds_load("keybindings.cfg", DT_USER)) 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; bool success = false;
const int MAX_KEYBIND_LEN = 128; const int MAX_KEYBIND_LEN = 128;
const int MAX_LINE_LEN = 512; 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) if(!config_file)
{ {
log_error("input:keybinds_load", "Could not open %s", filename); 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)); strncpy(key_name, start_loc, (keys - start_loc));
//log_message("key_name : %s", key_name); //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) 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 */ /* Copy the last key after the hyphen */
strncpy(key_name, start_loc, max_key_str_len); 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) if(key == KEY_UNKNOWN)
{ {
log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); 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; 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) if(!config_file)
{ {
log_error("input:keybinds_save", "Could not open %s", filename); 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, ", "); if(j != 0) fprintf(config_file, ", ");
struct Key_Combination* key_comb = &map->keys[j]; 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_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_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)); 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, "%s", platform->key_name_get(key_comb->key));
} }
fprintf(config_file, "\n"); 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) void input_mouse_pos_get(int* xpos, int* ypos)
{ {
assert(xpos && 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) 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) 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) 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) 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) 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) 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; return state_type == current_state ? true : false;
} }
@ -440,12 +439,12 @@ int map_find(const char* name)
int input_mouse_mode_get(void) int input_mouse_mode_get(void)
{ {
int mouse_mode = MM_NORMAL; 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; return mouse_mode;
} }
void input_mouse_delta_get(int* xpos, int* ypos) void input_mouse_delta_get(int* xpos, int* ypos)
{ {
platform_mouse_delta_get(xpos, ypos); platform->mouse_delta_get(xpos, ypos);
} }

@ -4,7 +4,6 @@
#include <time.h> #include <time.h>
#include "log.h" #include "log.h"
#include "platform.h"
#ifdef __linux__ #ifdef __linux__
#define COLOURED_STDOUT #define COLOURED_STDOUT
@ -32,15 +31,14 @@
static FILE* log_file = NULL; 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'}; 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"); log_file = fopen(log_file_path, "w");
if(!log_file) 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 else
{ {
@ -49,7 +47,8 @@ void log_init(const char* log_file_name)
fprintf(log_file, "Log Initialized at %s\n", ctime(&current_time)); fprintf(log_file, "Log Initialized at %s\n", ctime(&current_time));
fflush(log_file); fflush(log_file);
} }
if(dir) free(dir); // Disable stdout buffering
setbuf(stdout, NULL);
} }
void log_cleanup(void) void log_cleanup(void)
@ -115,3 +114,13 @@ void log_error(const char* context, const char* error, ...)
fprintf(log_file, "\n"); fprintf(log_file, "\n");
fflush(log_file); fflush(log_file);
} }
FILE* log_file_handle_get(void)
{
return log_file;
}
void log_file_handle_set(FILE* file)
{
log_file = file;
}

@ -1,11 +1,15 @@
#ifndef LOG_H #ifndef LOG_H
#define LOG_H #define LOG_H
void log_init(const char* log_file_name); #include <stdio.h>
void log_init(const char* log_file_name, const char* user_directory);
void log_cleanup(void); void log_cleanup(void);
void log_message(const char* message, ...); void log_message(const char* message, ...);
void log_warning(const char* message, ...); void log_warning(const char* message, ...);
void log_error(const char* context, const char* error, ...); void log_error(const char* context, const char* error, ...);
void log_to_stdout(const char* message, ...); /* Only use when logging is not initialized */ 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 #endif

@ -2,24 +2,109 @@
#include <stdlib.h> #include <stdlib.h>
#include "log.h" #include "log.h"
#include "sound.h"
#include "platform.h" #include "platform.h"
#include "gl_load.h" #include "gl_load.h"
#include "game.h"
#include "file_io.h" #include "file_io.h"
#include "config_vars.h" #include "config_vars.h"
#include "hashmap.h" #include "hashmap.h"
#include "common.h"
static struct Window* window = NULL; static struct Window* window = NULL;
static struct Platform_Api platform_api;
struct Game_Api game;
void* game_lib_handle = NULL;
bool init(); bool init(void);
void cleanup(); void cleanup(void);
bool game_lib_load(void);
bool game_lib_reload(void);
int main(int argc, char** args) int main(int argc, char** args)
{ {
if(!init()) if(!init())
{
log_to_stdout("ERR:(Main) Could not initialize"); log_to_stdout("ERR:(Main) Could not initialize");
}
else 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); exit(EXIT_SUCCESS);
} }
@ -35,10 +120,9 @@ bool init(void)
config_vars_init(); config_vars_init();
if(!platform_init()) return false; if(!platform_init()) return false;
log_init("Log.txt");
char* install_path = platform_install_directory_get(); char* install_path = platform_install_directory_get();
char* user_path = platform_user_directory_get("SS_Games", "Symmetry"); char* user_path = platform_user_directory_get("SS_Games", "Symmetry");
log_init("Log.txt", user_path);
io_file_init(install_path, user_path); io_file_init(install_path, user_path);
free(install_path); free(install_path);
free(user_path); free(user_path);
@ -50,7 +134,7 @@ bool init(void)
if(!platform_init_video()) return false; if(!platform_init_video()) return false;
if(!gl_load_library()) if(!platform_load_gl(NULL))
{ {
log_error("main:init", "Initializing OpenGL failed"); log_error("main:init", "Initializing OpenGL failed");
return false; return false;
@ -68,9 +152,15 @@ bool init(void)
return false; 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; return false;
} }
@ -79,9 +169,49 @@ bool init(void)
void cleanup() 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(); platform_cleanup();
config_vars_cleanup(); config_vars_cleanup();
io_file_cleanup();
log_message("Program exiting!"); log_message("Program exiting!");
log_cleanup(); 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;
}

@ -1,12 +1,13 @@
#include "platform.h" #include "platform.h"
#include "log.h" #include "log.h"
#include "input.h"
#include "config_vars.h" #include "config_vars.h"
#include "hashmap.h" #include "hashmap.h"
#include "string_utils.h" #include "string_utils.h"
#include <SDL2/SDL.h>
static int current_video_driver = VD_DUMMY; #include <SDL2/SDL.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
struct Window struct Window
{ {
@ -451,3 +452,59 @@ char* platform_user_directory_get(const char* organization, const char* applicat
} }
return user_directory; 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;
}

@ -1,7 +1,7 @@
#ifndef PLATFORM_H #ifndef PLATFORM_H
#define PLATFORM_H #define PLATFORM_H
#include "num_types.h" #include "common.h"
enum Video_Drivers_Linux enum Video_Drivers_Linux
{ {
@ -10,14 +10,6 @@ enum Video_Drivers_Linux
VD_DUMMY 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 // Window Related functions
struct Window; struct Window;
@ -59,5 +51,11 @@ void platform_clipboard_text_set(const char* text);
char* platform_clipboard_text_get(void); char* platform_clipboard_text_get(void);
int platform_key_from_name(const char* key_name); int platform_key_from_name(const char* key_name);
const char* platform_key_name_get(int key); 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 #endif

@ -14,12 +14,12 @@
#include "transform.h" #include "transform.h"
#include "game.h" #include "game.h"
#include "gui.h" #include "gui.h"
#include "config_vars.h"
#include "hashmap.h" #include "hashmap.h"
#include "geometry.h" #include "geometry.h"
#include "material.h" #include "material.h"
#include "editor.h" #include "editor.h"
#include "variant.h" #include "variant.h"
#include "common.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -46,7 +46,7 @@ void renderer_init(void)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); glCullFace(GL_BACK);
platform_windowresize_callback_set(on_framebuffer_size_change); platform->windowresize_callback_set(on_framebuffer_size_change);
gui_init(); gui_init();
/* Quad geometry for final render */ /* Quad geometry for final render */
@ -81,7 +81,7 @@ void renderer_init(void)
int width = -1, height = -1; int width = -1, height = -1;
struct Game_State* game_state = game_state_get(); 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", def_albedo_tex = texture_create("def_albedo_texture",
TU_DIFFUSE, TU_DIFFUSE,
width, height, width, height,
@ -353,7 +353,7 @@ void renderer_draw(struct Entity* active_viewer)
/* Final Render */ /* Final Render */
int width, height; int width, height;
struct Game_State* game_state = game_state_get(); 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); glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader_bind(composition_shader); shader_bind(composition_shader);
@ -365,7 +365,7 @@ void renderer_draw(struct Entity* active_viewer)
shader_unbind(); shader_unbind();
/* Debug Render */ /* Debug Render */
struct Hashmap* cvars = config_vars_get(); struct Hashmap* cvars = platform->config.get();
if(hashmap_bool_get(cvars, "debug_draw_enabled")) if(hashmap_bool_get(cvars, "debug_draw_enabled"))
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 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) 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); hashmap_bool_set(cvars, "debug_draw_enabled", enabled);
} }
void renderer_settings_get(struct Render_Settings* settings) 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.mode = hashmap_int_get(cvars, "fog_mode");
settings->fog.density = hashmap_float_get(cvars, "fog_density"); settings->fog.density = hashmap_float_get(cvars, "fog_density");
settings->fog.start_dist = hashmap_float_get(cvars, "fog_start_dist"); 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) 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_int_set(cvars, "fog_mode", settings->fog.mode);
hashmap_float_set(cvars, "fog_density", settings->fog.density); hashmap_float_set(cvars, "fog_density", settings->fog.density);
hashmap_float_set(cvars, "fog_start_dist", settings->fog.start_dist); hashmap_float_set(cvars, "fog_start_dist", settings->fog.start_dist);

@ -3,7 +3,7 @@
#include "entity.h" #include "entity.h"
#include "log.h" #include "log.h"
#include "transform.h" #include "transform.h"
#include "file_io.h" #include "common.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -125,7 +125,7 @@ struct Entity* scene_get_parent(struct Entity* entity)
bool scene_load(const char* filename, int directory_type) bool scene_load(const char* filename, int directory_type)
{ {
bool success = false; 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) if(!entity_file)
{ {
log_error("scene:load", "Failed to open scenefile %s for writing", filename); log_error("scene:load", "Failed to open scenefile %s for writing", filename);

@ -1,5 +1,4 @@
#include "shader.h" #include "shader.h"
#include "file_io.h"
#include "array.h" #include "array.h"
#include "num_types.h" #include "num_types.h"
#include "string_utils.h" #include "string_utils.h"
@ -7,6 +6,7 @@
#include "renderer.h" #include "renderer.h"
#include "texture.h" #include "texture.h"
#include "gl_load.h" #include "gl_load.h"
#include "common.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -56,7 +56,7 @@ char* run_preprocessor(char* shader_text)
{ {
char* path = str_new("shaders/"); char* path = str_new("shaders/");
path = str_concat(path, filename); 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* shader_copy = str_new(shader_text);
char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2)); char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2));
if(temp) 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 vert_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER); GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
char* vert_source = io_file_read(DT_INSTALL, vs_path, "r", NULL); char* vert_source = platform->file.read(DT_INSTALL, vs_path, "r", NULL);
char* frag_source = io_file_read(DT_INSTALL, fs_path, "r", NULL); char* frag_source = platform->file.read(DT_INSTALL, fs_path, "r", NULL);
assert(vert_source != NULL); assert(vert_source != NULL);
assert(frag_source != NULL); assert(frag_source != NULL);

@ -1,7 +1,5 @@
#include "sound.h" #include "sound.h"
#include "log.h" #include "log.h"
#include "transform.h"
#include "entity.h"
#include "array.h" #include "array.h"
#include "string_utils.h" #include "string_utils.h"
#include "file_io.h" #include "file_io.h"
@ -15,7 +13,6 @@
struct Sound_State struct Sound_State
{ {
int listener_entity;
ALCdevice* device; ALCdevice* device;
ALCcontext* context; ALCcontext* context;
float volume; float volume;
@ -23,7 +20,6 @@ struct Sound_State
static struct Sound_State sound_state = static struct Sound_State sound_state =
{ {
.listener_entity = -1,
.device = NULL, .device = NULL,
.context = NULL, .context = NULL,
.volume = 0.f .volume = 0.f
@ -32,7 +28,6 @@ static struct Sound_State sound_state =
bool sound_init(void) bool sound_init(void)
{ {
bool success = false; bool success = false;
sound_state.device = alcOpenDevice(NULL); sound_state.device = alcOpenDevice(NULL);
if(!sound_state.device) if(!sound_state.device)
{ {
@ -51,7 +46,6 @@ bool sound_init(void)
log_message("Opened %s", alcGetString(sound_state.device, ALC_DEVICE_SPECIFIER)); log_message("Opened %s", alcGetString(sound_state.device, ALC_DEVICE_SPECIFIER));
/* Set default listener values */ /* Set default listener values */
sound_state.listener_entity = -1;
sound_state.volume = 1.f; sound_state.volume = 1.f;
float orientation[] = float orientation[] =
{ {
@ -66,67 +60,36 @@ bool sound_init(void)
return success; return success;
} }
void sound_listener_set(int listener_entity) void sound_listener_update(float apos_x, float apos_y, float apos_z,
{ float afwd_x, float afwd_y, float afwd_z,
assert(listener_entity > -1); float aup_x, float aup_y, float aup_z)
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);
float orientation[] = float orientation[] =
{ {
abs_forward.x, abs_forward.y, abs_forward.z, afwd_x, afwd_y, afwd_z,
abs_up.x, abs_up.y, abs_up.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)) al_check(alListenerfv(AL_ORIENTATION, orientation))
} }
int sound_listener_get(void)
{
return sound_state.listener_entity;
}
void sound_volume_set(float volume) void sound_volume_set(float volume)
{ {
if(volume < 0.f) volume = 0.f; if(volume < 0.f) volume = 0.f;
al_check(alListenerf(AL_GAIN, volume)) 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)
{
for(int i = 0; i < (int)num_buffers; i++)
{ {
assert(entity && entity->type == ET_SOUND_SOURCE); if(alIsBuffer(attached_buffers[i]) == AL_TRUE)
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_handle, AL_BUFFER, i))
al_check(alSourcei(source->al_source_handle, AL_BUFFER, 0)) al_check(alDeleteBuffers(1, &attached_buffers[i]))
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; if(alIsSource(source_handle) == AL_TRUE) al_check(alDeleteSources(1, &source_handle))
source->al_source_handle = 0;
source->active = false;
} }
void sound_cleanup(void) void sound_cleanup(void)
@ -137,7 +100,6 @@ void sound_cleanup(void)
sound_state.context = NULL; sound_state.context = NULL;
sound_state.device = NULL; sound_state.device = NULL;
sound_state.volume = 0.f; sound_state.volume = 0.f;
sound_state.listener_entity = -1;
} }
void sound_error_check(const char* file, unsigned int line, const char* expression) 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); al_check(alGenSources(1, out_handle))
struct Sound_Source* source = &entity->sound_source; al_check(alGenBuffers((int)num_buffers, out_buffer_handles))
source->active = true; sound_source_volume_set(*out_handle, 1.f);
al_check(alGenSources(1, &source->al_source_handle))
al_check(alGenBuffers(1, &source->al_buffer_handle))
sound_source_volume_set(entity, 1.f);
if(relative) if(relative)
sound_source_relative_set(entity, true); sound_source_relative_set(*out_handle, true);
else
sound_source_update(entity);
} }
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[] = float orientation[] =
{ {
abs_forward.x, abs_forward.y, abs_forward.z, afwd_x, afwd_y, afwd_z,
abs_up.x, abs_up.y, abs_up.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(alSource3f(source_handle, AL_POSITION, apos_x, apos_y, apos_z))
al_check(alSourcefv(entity->sound_source.al_source_handle, AL_ORIENTATION, orientation)) 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; 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; 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; 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; relative = relative ? AL_TRUE : AL_FALSE;
al_check(alSourcei(entity->sound_source.al_source_handle, AL_SOURCE_RELATIVE, relative)); al_check(alSourcei(source_handle, AL_SOURCE_RELATIVE, relative));
entity->sound_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) if(!file_name)
{ {
log_error("sound_source:load_wav", "No file name given"); 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; return;
} }
struct Sound_Source* source = &entity->sound_source; al_check(alBufferData(buffer_handle, format, wav_data, wav_data_len, wav_spec.freq))
al_check(alBufferData(source->al_buffer_handle, format, wav_data, wav_data_len, wav_spec.freq)) al_check(alSourcei(source_handle, AL_BUFFER, buffer_handle))
al_check(alSourcei(source->al_source_handle, AL_BUFFER, source->al_buffer_handle))
SDL_FreeWAV(wav_data); 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(source_handle))
al_check(alSourcePlay(entity->sound_source.al_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(source_handle))
al_check(alSourcePause(entity->sound_source.al_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(source_handle))
al_check(alSourceRewind(entity->sound_source.al_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(source_handle))
al_check(alSourceStop(entity->sound_source.al_source_handle))
} }

@ -9,28 +9,29 @@
#define al_check(expr) expr; #define al_check(expr) expr;
#endif #endif
struct Entity;
bool sound_init(void); bool sound_init(void);
void sound_cleanup(void); void sound_cleanup(void);
void sound_volume_set(float volume); void sound_volume_set(float volume);
void sound_error_check(const char* file, unsigned int line, const char* expression); void sound_error_check(const char* file, unsigned int line, const char* expression);
void sound_listener_set(int entity); void sound_listener_update(float apos_x, float apos_y, float apos_z,
int sound_listener_get(void); float afwd_x, float afwd_y, float afwd_z,
void sound_listener_update(void); float aup_x, float aup_y, float aup_z);
void sound_source_create(struct Entity* entity, bool relative); void sound_source_update(uint source_handle,
void sound_source_destroy(struct Entity* entity); float apos_x, float apos_y, float apos_z,
void sound_source_update(struct Entity* entity); float afwd_x, float afwd_y, float afwd_z,
void sound_source_volume_set(struct Entity* entity, float volume); float aup_x, float aup_y, float aup_z);
void sound_source_pitch_set(struct Entity* entity, float pitch); void sound_source_create(bool relative, uint num_buffers, uint* out_handle, uint* out_buffer_handles);
void sound_source_load_wav(struct Entity* entity, const char* file_name); void sound_source_destroy(uint source_handle, uint* attached_buffers, uint num_buffers);
void sound_source_loop_set(struct Entity* entity, bool loop); void sound_source_volume_set(uint source_handle, float volume);
void sound_source_relative_set(struct Entity* entity, bool relative); void sound_source_pitch_set(uint source_handle, float pitch);
void sound_source_play(struct Entity* entity); void sound_source_load_wav(uint source_handle, uint buffer_handle, const char* file_name);
void sound_source_pause(struct Entity* entity); void sound_source_loop_set(uint source_handle, bool loop);
void sound_source_rewind(struct Entity* entity); void sound_source_relative_set(uint source_handle, bool relative);
void sound_source_stop(struct Entity* entity); 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 #endif

@ -1,11 +1,11 @@
#include "texture.h" #include "texture.h"
#include "array.h" #include "array.h"
#include "file_io.h"
#include "string_utils.h" #include "string_utils.h"
#include "log.h" #include "log.h"
#include "num_types.h" #include "num_types.h"
#include "renderer.h" #include "renderer.h"
#include "gl_load.h" #include "gl_load.h"
#include "common.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -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 */ /* If texture not already loaded then try to load it */
char* full_path = str_new("textures/%s", filename); 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; int img_load_success = -1;
if(file) if(file)

@ -29,6 +29,13 @@ void variant_assign_int(struct Variant* variant, const int value)
variant->val_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) void variant_assign_double(struct Variant* variant, const double value)
{ {
if(variant->type != VT_DOUBLE) variant_free(variant); 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_BOOL: variant_assign_bool(to, from->val_bool); break;
case VT_INT: variant_assign_int(to, from->val_int); 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_FLOAT: variant_assign_float(to, from->val_float); break;
case VT_DOUBLE: variant_assign_double(to, from->val_double); break; case VT_DOUBLE: variant_assign_double(to, from->val_double); break;
case VT_VEC2: variant_assign_vec2(to, &from->val_vec2); 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_BOOL: snprintf(str, len, "%s", variant->val_bool ? "true" : "false"); break;
case VT_INT: snprintf(str, len, "%d", variant->val_int); 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_FLOAT: snprintf(str, len, "%.4f", variant->val_float); break;
case VT_DOUBLE: snprintf(str, len, "%.4f", variant->val_double); 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; case VT_VEC2: snprintf(str, len, "%.3f %.3f", variant->val_vec2.x, variant->val_vec2.y); break;
@ -218,6 +227,13 @@ void variant_from_str(struct Variant* variant, const char* str, int variant_type
if(sscanf(str, "%d", &int_val) == 1) if(sscanf(str, "%d", &int_val) == 1)
variant_assign_int(variant, int_val); 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; break;
case VT_FLOAT: case VT_FLOAT:
{ {
@ -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_BOOL: *(bool*)to = from->val_bool; break;
case VT_INT: *(int*)to = from->val_int; 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_FLOAT: *(float*)to = from->val_float; break;
case VT_DOUBLE: *(double*)to = from->val_double; break; case VT_DOUBLE: *(double*)to = from->val_double; break;
case VT_VEC2: vec2_assign((vec2*)to, &from->val_vec2); break; case VT_VEC2: vec2_assign((vec2*)to, &from->val_vec2); break;

@ -11,6 +11,7 @@ enum Variant_Type
VT_NONE = 0, VT_NONE = 0,
VT_BOOL, VT_BOOL,
VT_INT, VT_INT,
VT_UINT,
VT_FLOAT, VT_FLOAT,
VT_DOUBLE, VT_DOUBLE,
VT_STR, VT_STR,
@ -29,6 +30,7 @@ struct Variant
union union
{ {
int val_int; int val_int;
uint val_uint;
bool val_bool; bool val_bool;
float val_float; float val_float;
double val_double; double val_double;
@ -45,6 +47,7 @@ struct Variant
void variant_init_empty(struct Variant* variant); void variant_init_empty(struct Variant* variant);
void variant_assign_float(struct Variant* variant, const float value); void variant_assign_float(struct Variant* variant, const float value);
void variant_assign_int(struct Variant* variant, const int 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_double(struct Variant* variant, const double value);
void variant_assign_bool(struct Variant* variant, const bool value); void variant_assign_bool(struct Variant* variant, const bool value);
void variant_assign_str(struct Variant* variant, const char* value); void variant_assign_str(struct Variant* variant, const char* value);

Loading…
Cancel
Save