From 132e49f434ce0893748a941738f60a300f41b41c Mon Sep 17 00:00:00 2001 From: shariq Date: Sun, 20 Aug 2017 23:38:45 +0500 Subject: [PATCH] Added support for launching under wayland on linux and ability to select between x11 and wayland through config file --- README.md | 47 ++++++++++++++++------ assets/config.cfg | 3 +- src/config_vars.c | 4 +- src/entity.c | 30 +++++++------- src/main.c | 99 ++++++++++++++++++++++------------------------- src/platform.c | 40 ++++++++++++++++--- src/platform.h | 10 ++++- src/scene.c | 14 ++++++- src/scene.h | 4 +- 9 files changed, 161 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index 359f22e..8e6db7c 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ - ## File format specifications - ### Entity + ```.conf - :::conf # Comment, Sample entity definition in file, paremeters left out are set to defaults # Empty line at the end specifies end of entity definition entity: "Something" @@ -23,9 +23,10 @@ diffuse_texture: "checkered.tga" specular: 0.55 ``` - - Add to_string functions for major structs like transform, model etc to ease in conversion? + - Add to_string functions for major structs like transform, model etc to ease in conversion? - ### Configuration Variables a.k.a cfg-vars + ```.conf # Comment render_width: 1024 @@ -41,7 +42,8 @@ ``` - ### Keybindings - ```.conf + + ```.conf # All keys are parsed by comparing the output of SDL_GetKeyname # Each line represents a keybinding Move_Forward: W @@ -58,28 +60,45 @@ # Single modifier keys are allowed but multiple modifier keys without corresponding # non-modifier key are not allowed Sprint: Left Shift - ``` + ``` + - ### Level/Scene + - Binary format with header attached at the top - Save child entities first - Copy paste all entites in the file one by one. Since the entites all look - the same in memory and are made up of tagged unions, a simple memcpy approach - should suffice. The problem is entity heirarchies. There are multiple approaches to - solve this problem. - - Save a sorted list of entites to file i.e. before saving create a new list that does + the same in memory and are made up of tagged unions, a simple memcpy approach + should suffice. The problem is entity heirarchies. There are multiple approaches to + solve this problem. + - Save a sorted list of entites to file i.e. before saving create a new list that does not have the empty array slots in the entity list and then just copy and paste. This is the simplest way to solve the problem as we don't have to worry about indexes of parent/child entites in heirarchy. We can take the whole array and paste it to the file but creating a copy of entity list for this purpose only would be slow and consume a lot of memory. - - Instead of creating a copy of the entity list for sorting and saving, sort the actual entity list + - Instead of creating a copy of the entity list for sorting and saving, sort the actual entity list and update all references as necessary then save the array to file. - - Just write the name of the parent entity as parent. Make sure that all entity names are unique. + - Just write the name of the parent entity as parent. Make sure that all entity names are unique. + - Use separate EntityDefinition file that serves as a blueprint/prefab for the entity + to load/save. When the entity is saved in a scene file, the scene file only needs to + refer to the entity's EntityDefinition file/asset along with it's parent and children + - This approach requires seperating a scene into mutable/immutable parts. + Meaning, entities that can change their state during the duaration of the level are + mutable and those that remain the same as they were defined in their EntityDefinition + file are immutable. + - In each level there going to be mutable entites i.e player and player's position/orientation, objectives + cleared/remaining, doors opened and puzzles solved etc. Instead of handling all of these in the + scene file, we save all the mutable state in the savegame files. When restoring game's state from a save game we will need + to handle loading of a scene and then applying the mutable state to entites after loading. + - Entities can have (a fixed number of?) properties. Each property has a name and a corresponding + variant value like, health or ammo etc. But, how to save/load all of that? + - ### Materials - ### Mesh/Geometry - ### Notes on entity Systems - - Fat entites with all related properties, i.e. position, mesh etc in them. Easy to serialize, memory friendly, simple to implement but would require significant changes to the current codebase, for example: + - Fat entites with all related properties, i.e. position, mesh etc in them. Easy to serialize, memory friendly, simple to implement but would require significant changes to the current codebase, for example: + ```.C struct Entity { @@ -108,7 +127,9 @@ } }; ``` + - Change component implementation by using anonymous unions to simulate interfaces. e.g + ```.C struct Component { @@ -121,6 +142,7 @@ } } ``` + - Use handles for assets - Use something similar to Variant to use as entity, not sure what or how - Don't forget to think of the actual use-case and usage when coming up with a solution, don't build castles in the air! @@ -134,6 +156,7 @@ ? Minimal custom UI for in-game usage that can be rendered to a texture or modify nuklear for that? - Bounding Boxes ? Recalculated bounding boxes for rotated meshes + - Wrap malloc and free calls in custom functions to track usage - File extension checking for asset loading - Only allocate hashmap bucket when required - Mapping actions to keybindings, for example map action "Jump" to Space key etc @@ -181,7 +204,6 @@ - Make logging to file and console toggleable at complie-time or run-time - Add default keybindings - Write default config/keybindings etc to file if none are found in preferences dir - - Wrap malloc and free calls in custom functions to track usage - Flatpak packaging for linux releases - Use hashmap for debugvar slots in editor - Use hashmap to store input maps @@ -273,3 +295,4 @@ * Replace orgfile with simple text readme and reduce duplication * 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. diff --git a/assets/config.cfg b/assets/config.cfg index 4cf5e9d..cad42d8 100644 --- a/assets/config.cfg +++ b/assets/config.cfg @@ -10,4 +10,5 @@ msaa_enabled : true fog_start_dist : 20.0000 debug_draw_enabled : false debug_draw_mode : 0 -ambient_light : 0.100, 0.100, 0.100 \ No newline at end of file +ambient_light : 0.100, 0.100, 0.100 +video_driver_linux : 1 diff --git a/src/config_vars.c b/src/config_vars.c index aac33a1..0b6153b 100644 --- a/src/config_vars.c +++ b/src/config_vars.c @@ -4,6 +4,7 @@ #include "hashmap.h" #include "file_io.h" #include "log.h" +#include "platform.h" #include #include @@ -27,8 +28,9 @@ void config_vars_init(void) hashmap_bool_set(cvars, "msaa_enabled", 1); hashmap_int_set(cvars, "msaa_levels", 4); hashmap_bool_set(cvars, "debug_draw_enabled", 1); + hashmap_int_set(cvars, "video_driver_linux", VD_WAYLAND); hashmap_int_set(cvars, "debug_draw_mode", 0); - hashmap_vec4_setf(cvars, "debug_draw_color", 1.f, 0.f, 0.f, 1.f); + hashmap_vec4_setf(cvars, "debug_draw_color", 1.f, 0.f, 0.f, 1.f); } void config_vars_cleanup(void) diff --git a/src/entity.c b/src/entity.c index a4fea4d..bce5686 100644 --- a/src/entity.c +++ b/src/entity.c @@ -257,32 +257,34 @@ struct Entity* entity_load(const char* filename, int directory_type) FILE* entity_file = io_file_open(directory_type, filename, "r"); if(!entity_file) { - log_error("entity:load", "Failed to open entity file %s for writing"); + log_error("entity:load", "Failed to open entity file %s for writing", filename); return NULL; } struct Entity entity = - { - .id = -1, - .type = ET_NONE, - .is_listener = false, - .renderable = false, - .marked_for_deletion = false, - .name = "DEFAULT_ENTITY_NAME", - .editor_selected = 0 - }; + { + .id = -1, + .type = ET_NONE, + .is_listener = false, + .renderable = false, + .marked_for_deletion = false, + .name = "DEFAULT_ENTITY_NAME", + .editor_selected = 0 + }; + int current_line = 0; char* material_name = NULL; char* entity_name = NULL; char* geometry_name = NULL; char* parent_name = NULL; + char line_buffer[MAX_LINE_LEN]; + char prop_str[MAX_ENTITY_PROP_NAME_LEN]; static struct Variant var_value = { .type = VT_NONE}; - char prop_str[MAX_ENTITY_PROP_NAME_LEN]; - char line_buffer[MAX_LINE_LEN]; + + variant_free(&var_value); memset(prop_str, '\0', MAX_ENTITY_PROP_NAME_LEN); memset(line_buffer, '\0', MAX_LINE_LEN); - int current_line = 0; - variant_free(&var_value); + while(fgets(line_buffer, MAX_LINE_LEN -1, entity_file)) { current_line++; diff --git a/src/main.c b/src/main.c index 5565238..0782177 100644 --- a/src/main.c +++ b/src/main.c @@ -11,7 +11,7 @@ static struct Window* window = NULL; -int init(); +bool init(); void cleanup(); int main(int argc, char** args) @@ -24,62 +24,57 @@ int main(int argc, char** args) exit(EXIT_SUCCESS); } -int init(void) +bool init(void) { - int success = 1; if(atexit(cleanup) != 0) { - success = 0; log_to_stdout("ERR: (main:init) Could not register cleanup func with atexit"); + return false; } - else - { - config_vars_init(); - if(platform_init()) - { - log_init("Log.txt"); - success = gl_load_library(); - if(!success) - { - log_error("main:init", "Initializing OpenGL failed"); - } - else - { - char* install_path = platform_install_directory_get(); - char* user_path = platform_user_directory_get("SS_Games", "Symmetry"); - io_file_init(install_path, user_path); - free(install_path); - free(user_path); - if(!config_vars_load("config.cfg", DT_USER)) - { - log_error("main:init", "Could not load config, reverting to defaults"); - config_vars_save("config.cfg", DT_USER); - } - - struct Hashmap* cvars = config_vars_get(); - int width = hashmap_int_get(cvars, "render_width"); - int height = hashmap_int_get(cvars, "render_height"); - int msaa = hashmap_bool_get(cvars, "msaa_enabled"); - int msaa_levels = hashmap_int_get(cvars, "msaa_levels"); - window = window_create("Symmetry", width, height, msaa, msaa_levels); - if(!window) - { - log_error("main:init", "Window creation failed"); - success = 0; - } - else - { - success = gl_load_extentions(); - if(!success) log_error("main:init", "Failed to load opengl extentions"); - } - } - } - else - { - success = 0; - } - } - return success; + + 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"); + io_file_init(install_path, user_path); + free(install_path); + free(user_path); + if(!config_vars_load("config.cfg", DT_USER)) + { + log_error("main:init", "Could not load config, reverting to defaults"); + config_vars_save("config.cfg", DT_USER); + } + + if(!platform_init_video()) return false; + + if(!gl_load_library()) + { + log_error("main:init", "Initializing OpenGL failed"); + return false; + } + + struct Hashmap* cvars = config_vars_get(); + int width = hashmap_int_get(cvars, "render_width"); + int height = hashmap_int_get(cvars, "render_height"); + int msaa = hashmap_bool_get(cvars, "msaa_enabled"); + int msaa_levels = hashmap_int_get(cvars, "msaa_levels"); + window = window_create("Symmetry", width, height, msaa, msaa_levels); + if(!window) + { + log_error("main:init", "Window creation failed"); + return false; + } + + if(!gl_load_extentions()) + { + log_error("main:init", "Failed to load opengl extentions"); + return false; + } + + return true; } void cleanup() diff --git a/src/platform.c b/src/platform.c index bf23b77..6e55929 100644 --- a/src/platform.c +++ b/src/platform.c @@ -6,6 +6,8 @@ #include "string_utils.h" #include +static int current_video_driver = VD_DUMMY; + struct Window { void* sdl_window; @@ -169,12 +171,12 @@ void window_swap_buffers(struct Window* window) SDL_GL_SwapWindow(window->sdl_window); } -int platform_init(void) +bool platform_init(void) { - int success = 1; - if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0) + bool success = true; + if(SDL_Init(SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0) { - success = 0; + success = false; if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL Init failed", SDL_GetError(), NULL) != 0) log_to_stdout("platform_init", "SDL Init failed : %s", SDL_GetError()); } @@ -185,7 +187,7 @@ int platform_init(void) { if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Allocation Failure", "Memory allocation failed, out of memory!", NULL) != 0) log_to_stdout("platform_init", "Could not create platform state, out of memory"); - success = 0; + success = false; } else { @@ -200,10 +202,38 @@ int platform_init(void) return success; } +bool platform_init_video() +{ + bool success = true; + const char* video_driver_str = NULL; + +#ifdef __linux__ + struct Hashmap* cvars = config_vars_get(); + int driver_type = hashmap_bool_get(cvars, "video_driver_linux"); + switch (driver_type) + { + case VD_WAYLAND: video_driver_str = "wayland"; break; + case VD_X11: video_driver_str = "x11"; break; + }; +#endif + + if(SDL_VideoInit(video_driver_str) != 0) + { + log_error("platform:init_video", "Failed to initialize video subsystem, SDL : (%s)", SDL_GetError()); + success = false; + } + else + { + log_message("Video subsystem initialized with %s", SDL_GetCurrentVideoDriver()); + } + return success; +} + void platform_cleanup(void) { if(platform_state) free(platform_state); platform_state = NULL; + SDL_VideoQuit(); SDL_Quit(); } diff --git a/src/platform.h b/src/platform.h index c715f5d..5d15e10 100644 --- a/src/platform.h +++ b/src/platform.h @@ -3,6 +3,13 @@ #include "num_types.h" +enum Video_Drivers_Linux +{ + VD_X11 = 0, + VD_WAYLAND, + 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); @@ -27,7 +34,8 @@ void window_swap_buffers(struct Window* window); int window_fullscreen_set(struct Window* window, int fullscreen); // Platform functions -int platform_init(void); +bool platform_init(void); +bool platform_init_video(void); void platform_cleanup(void); void platform_poll_events(bool *out_quit); void platform_keyboard_callback_set(Keyboard_Event_Func func); diff --git a/src/scene.c b/src/scene.c index afa0cc5..4b60fbb 100644 --- a/src/scene.c +++ b/src/scene.c @@ -3,6 +3,7 @@ #include "entity.h" #include "log.h" #include "transform.h" +#include "file_io.h" #include #include @@ -121,13 +122,22 @@ struct Entity* scene_get_parent(struct Entity* entity) return parent; } -bool scene_load(const char* filename) +bool scene_load(const char* filename, int directory_type) { bool success = false; + FILE* entity_file = io_file_open(directory_type, filename, "r"); + if(!entity_file) + { + log_error("scene:load", "Failed to open scenefile %s for writing", filename); + return NULL; + } + + struct Entity* root = entity_get(root_node); + return success; } -bool scene_save(const char* filename) +bool scene_save(const char* filename, int directory_type) { bool success = false; return success; diff --git a/src/scene.h b/src/scene.h index 5c447eb..8bb5f7e 100644 --- a/src/scene.h +++ b/src/scene.h @@ -15,8 +15,8 @@ struct Entity* scene_find(const char* name); struct Entity* scene_get_root(void); struct Entity* scene_get_child_by_name(struct Entity* parent, const char* name); struct Entity* scene_get_parent(struct Entity* entity); -bool scene_load(const char* filename); -bool scene_save(const char* filename); +bool scene_load(const char* filename, int directory_type); +bool scene_save(const char* filename, int directory_type); #endif