From 569e203409993ea1d34bff910b80f72adb47b690 Mon Sep 17 00:00:00 2001 From: frank <420@shampoo.ooo> Date: Fri, 2 Jul 2021 22:42:48 -0400 Subject: [PATCH] move gl attributes to right before opening gl context; file to string func --- src/Game.cpp | 305 +++++++++++++++++++++++++++------------------- src/Game.hpp | 15 ++- src/Recorder.cpp | 15 +-- src/extension.cpp | 35 +++++- src/extension.hpp | 6 +- 5 files changed, 229 insertions(+), 147 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index 16ed443..6a4a94f 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -41,8 +41,8 @@ void FramerateIndicator::refresh() Game::Game() { - // set the appropriate priority level for the default log category so either info level messages - // and higher are enabled or debug level messages are enabled, depending on the global configuration + /* Set the appropriate priority level for the default log category so either info level messages + * and higher are enabled or debug level messages are enabled, depending on the global configuration */ SDL_LogPriority default_log_category_priority; if (get_configuration()["log"]["debug-to-file"] || get_configuration()["log"]["debug-to-stdout"]) { @@ -53,44 +53,43 @@ Game::Game() default_log_category_priority = SDL_LOG_PRIORITY_INFO; } SDL_LogSetPriority(DEFAULT_SDL_LOG_CATEGORY, default_log_category_priority); - // set custom log function (prints to stdout/stderr and to file if enabled) + /* set custom log function that prints to stdout/stderr and to file if enabled */ SDL_LogSetOutputFunction(&Game::sdl_log_override, this); - // pretty print config to debug log - std::stringstream config_formatted; - config_formatted << std::setw(4) << get_configuration() << std::endl; - SDL_LogDebug(DEFAULT_SDL_LOG_CATEGORY, "%s", config_formatted.str().c_str()); + /* pretty print config to debug log */ + std::ostringstream log_message; + log_message << std::setw(4) << get_configuration() << std::endl; + debug(log_message.str()); + /* tell SDL which render driver you will be requesting when calling SDL_CreateRenderer */ SDL_SetHint(SDL_HINT_RENDER_DRIVER, get_configuration()["display"]["render driver"].get().c_str()); + /* initialize the buffer of frame lengths which will be used to calculate FPS */ frame_length_history.reserve(5000); set_framerate(get_configuration()["display"]["framerate"]); delegate.subscribe(&Game::handle_quit_event, this, SDL_QUIT); - putenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN=0"); - // putenv("SDL_VIDEO_CENTERED=0"); + /* Needed for displaying fullscreen correctly on Linux (?) Also might need SDL_VIDEO_CENTERED (?) */ + std::string fullscreen_env_assigment = "SDL_VIDEO_X11_LEGACY_FULLSCREEN=0"; + putenv(const_cast(fullscreen_env_assigment.c_str())); + /* log compiled and linked SDL versions */ SDL_version version; + log_message = std::ostringstream(); + SDL_VERSION(&version); + log_message << "compiled against SDL " << static_cast(version.major) << "." << static_cast(version.minor) << + "." << static_cast(version.patch) << std::endl; SDL_GetVersion(&version); - SDL_Log("SDL %d.%d.%d", version.major, version.minor, version.patch); - fprintf(stderr, "stderr test message\n"); + log_message << "linked to SDL " << static_cast(version.major) << "." << static_cast(version.minor) << "." << + static_cast(version.patch); + log(log_message.str()); + /* allows use of our own main function (?) see SDL_SetMainReady.html */ SDL_SetMainReady(); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - // print_gl_attributes(); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { print_sdl_error("SDL could not initialize"); flag_to_end(); } - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); - SDL_Log("GLEW %s", glewGetString(GLEW_VERSION)); - auto window_size = get_configuration()["display"]["dimensions"].get(); + log_message = std::ostringstream(); + log_message << "GLEW " << glewGetString(GLEW_VERSION); + log(log_message.str()); + glm::ivec2 window_size = get_configuration()["display"]["dimensions"].get(); + /* Create a window with dimensions set in the config, centered, and flagged to be usable in OpenGL context */ window = SDL_CreateWindow( get_configuration()["display"]["title"].get_ref().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, SDL_WINDOW_OPENGL); @@ -99,6 +98,9 @@ Game::Game() print_sdl_error("Could not create window"); flag_to_end(); } + /* Create an SDL renderer for clearing the screen to black and for logging renderer properties. Destroy renderer + * when finished. + */ if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr) { print_sdl_error("Could not create renderer"); @@ -107,8 +109,12 @@ Game::Game() else { int w, h; + /* log the renderer resolution */ SDL_GetRendererOutputSize(renderer, &w, &h); - SDL_Log("renderer output size is (%i, %i)", w, h); + log_message = std::ostringstream(); + log_message << "renderer output size is " << w << "x" << h; + log(log_message.str()); + /* clear screen to black */ SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); @@ -151,22 +157,89 @@ Game::Game() const int audio_device_count = SDL_GetNumAudioDevices(SDL_TRUE); for (int ii = 0; ii < audio_device_count; ii++) { - SDL_Log("Found audio capture device %i: %s", ii, - SDL_GetAudioDeviceName(ii, SDL_TRUE)); + SDL_Log("Found audio capture device %i: %s", ii, SDL_GetAudioDeviceName(ii, SDL_TRUE)); } audio.load_sfx(); audio.load_bgm(); #if SDL_BYTEORDER == SDL_BIG_ENDIAN - SDL_Log("big endian"); + log("big endian"); #else - SDL_Log("little endian"); + log("little endian"); #endif last_frame_timestamp = SDL_GetTicks(); } -Game::~Game() +void Game::load_sdl_context() { - get_delegate().unsubscribe(this); + if (glcontext != nullptr) + { + SDL_GL_DeleteContext(glcontext); + glcontext = nullptr; + } + SDL_RendererInfo renderer_info; + int render_driver_count = SDL_GetNumRenderDrivers(); + SDL_Log("Render drivers:"); + for (int ii = 0; ii < render_driver_count; ii++) + { + SDL_GetRenderDriverInfo(ii, &renderer_info); + log_renderer_info(renderer_info); + } + if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr) + { + print_sdl_error("Could not create renderer"); + flag_to_end(); + } + else + { + SDL_Log("Current renderer:"); + SDL_GetRendererInfo(renderer, &renderer_info); + log_renderer_info(renderer_info); + SDL_Log("Renderer supports the use of render targets? %d", SDL_RenderTargetSupported(renderer)); + } + is_gl_context = false; + log_display_mode(); +} + +void Game::load_gl_context() +{ + if (renderer != nullptr) + { + SDL_DestroyRenderer(renderer); + renderer = nullptr; + } + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + if ((glcontext = SDL_GL_CreateContext(window)) == nullptr) + { + print_sdl_error("Could not get GL context"); + flag_to_end(); + } + /* try enabling vsync */ + if (SDL_GL_SetSwapInterval(1) == 0) + { + log("enabled vsync"); + } + else + { + log("vsync not supported"); + } + GLenum error = glewInit(); + std::ostringstream message; + if (error != GLEW_OK) + { + message << "GLEW could not initialize " << glewGetErrorString(error); + print_error(message.str()); + } + message << "OpenGL " << glGetString(GL_VERSION) << ", renderer " << glGetString(GL_RENDERER) << ", shading language " << + glGetString(GL_SHADING_LANGUAGE_VERSION); + log(message.str()); + is_gl_context = true; + log_display_mode(); } /* Overrides SDL's default log function to log a message to stdout/stderr and, if log is enabled in the @@ -221,21 +294,6 @@ void Game::print_sdl_error(const std::string& message) sfw::print_sdl_error(message); } -void Game::print_gl_attributes() -{ - int major, minor; - SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); - SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); - SDL_Log("GL CONTEXT: %i, %i", major, minor); - int r, g, b, a, buf; - SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r); - SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g); - SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b); - SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a); - SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &buf); - SDL_Log("GL PIXELS: red: %i green: %i blue: %i alpha: %i", r, g, b, a); -} - void Game::print_frame_length_history() { for (float& frame_length : frame_length_history) @@ -245,65 +303,62 @@ void Game::print_frame_length_history() std::cout << std::endl; } -void Game::load_sdl_context() +/* Create, compile and return the ID of a GL shader from the GLSL code at path */ +GLuint Game::load_shader(const fs::path& path, GLenum type) const { - if (glcontext != nullptr) + GLuint shader = glCreateShader(type); + std::fstream file = std::fstream(path); + std::ostringstream message; + std::string contents = sfw::file_to_string(path); + glShaderSource(shader, 1, reinterpret_cast(&contents), 0); + // glShaderSource(shader, 1, const_cast(&buf), 0); + glCompileShader(shader); + GLint is_compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled); + if (is_compiled == GL_TRUE) { - SDL_GL_DeleteContext(glcontext); - glcontext = nullptr; - } - SDL_RendererInfo renderer_info; - int render_driver_count = SDL_GetNumRenderDrivers(); - SDL_Log("Render drivers:"); - for (int ii = 0; ii < render_driver_count; ii++) - { - SDL_GetRenderDriverInfo(ii, &renderer_info); - log_renderer_info(renderer_info); - } - if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr) - { - print_sdl_error("Could not create renderer"); - flag_to_end(); + message << "compiled shader at " << path; + log(message.str()); + return shader; } else { - SDL_Log("Current renderer:"); - SDL_GetRendererInfo(renderer, &renderer_info); - log_renderer_info(renderer_info); - SDL_Log("Renderer supports the use of render targets? %d", SDL_RenderTargetSupported(renderer)); + /* log error by allocating a string to copy the GL error message buffer into */ + std::string error_info; + GLint max_length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length); + error_info.resize(max_length, 0); + glGetShaderInfoLog(shader, error_info.size(), nullptr, error_info.data()); + message << "failed to compile " << path << ": " << error_info; + log(message.str()); + return -1; } - is_gl_context = false; - log_display_mode(); } -void Game::load_gl_context() +bool Game::link_shader(GLuint program) const { - if (renderer != nullptr) + glLinkProgram(program); + int is_linked; + glGetProgramiv(program, GL_LINK_STATUS, (int *) &is_linked); + std::ostringstream message; + if (is_linked == GL_TRUE) { - SDL_DestroyRenderer(renderer); - renderer = NULL; + message << "linked shader program " << program; + log(message.str()); + return true; } - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - // SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - print_gl_attributes(); - if ((glcontext = SDL_GL_CreateContext(window)) == NULL) + else { - print_sdl_error("Could not get GL context"); - flag_to_end(); + /* log error by allocating a string to copy the GL error message buffer into */ + std::string error_info; + GLint max_length; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &max_length); + error_info.resize(max_length, 0); + glGetProgramInfoLog(program, error_info.size(), nullptr, error_info.data()); + message << "failed linking shader program " << program << ": " << error_info; + log(message.str()); + return false; } - GLenum error = glewInit(); - if (error != GLEW_OK) - { - std::ostringstream message; - message << "GLEW could not initialize " << glewGetErrorString(error); - print_error(message.str()); - } - SDL_Log("OpenGL %s, renderer %s, shading language %s", - glGetString(GL_VERSION), glGetString(GL_RENDERER), - glGetString(GL_SHADING_LANGUAGE_VERSION)); - is_gl_context = true; - log_display_mode(); } /* Send an info priority message to SDL's log output function, which is overridden by our own member @@ -338,76 +393,65 @@ bool Game::log_gl_errors(std::string suffix) while ((error = glGetError()) != GL_NO_ERROR) { error_logged = true; + std::ostringstream message; if (error == GL_INVALID_ENUM) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_INVALID_ENUM, an unacceptable value is specified for an " - "enumerated argument %s", suffix.c_str()); + message << "GL_INVALID_ENUM, an unacceptable value is specified for an enumerated argument"; } else if (error == GL_INVALID_VALUE) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_INVALID_VALUE, a numeric argument is out of range %s", suffix.c_str()); + message << "GL_INVALID_VALUE, a numeric argument is out of range"; } else if (error == GL_INVALID_OPERATION) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_INVALID_OPERATION, the specified operation is not allowed " - "in the current state %s", suffix.c_str()); + message << "GL_INVALID_OPERATION, the specified operation is not allowed in the current state"; } else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is " - "not complete %s", suffix.c_str()); + message << "GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is not complete"; } else if (error == GL_OUT_OF_MEMORY) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_OUT_OF_MEMORY, there is not enough memory left to execute " - "the command %s", suffix.c_str()); + message << "GL_OUT_OF_MEMORY, there is not enough memory left to execute the command"; } else if (error == GL_STACK_UNDERFLOW) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_STACK_UNDERFLOW, an attempt has been made to perform an " - "operation that would cause an internal stack to underflow. %s", suffix.c_str()); + message << "GL_STACK_UNDERFLOW, an attempt has been made to perform an operation that would " << + "cause an internal stack to underflow"; } else if (error == GL_STACK_OVERFLOW) { - SDL_LogError( - SDL_LOG_CATEGORY_APPLICATION, - "GL_STACK_OVERFLOW, an attempt has been made to perform an " - "operation that would cause an internal stack to overflow. %s", suffix.c_str()); + message << "GL_STACK_OVERFLOW, an attempt has been made to perform an operation that would " << + "cause an internal stack to overflow"; } + if (!suffix.empty()) + { + message << " " << suffix; + } + log(message.str()); } return error_logged; } -// from SDL_GetCurrentDisplayMode.html +/* Write resolution, monitor refresh rate, and pixel format to the log. Code taken from SDL_GetCurrentDisplayMode.html + * on the SDL wiki */ void Game::log_display_mode() { SDL_DisplayMode current; + std::ostringstream message; for (int ii = 0; ii < SDL_GetNumVideoDisplays(); ii++) { int mode = SDL_GetCurrentDisplayMode(ii, ¤t); if (mode != 0) { - SDL_Log("Could not get display mode for video display #%d: %s", ii, - SDL_GetError()); + message << "Could not get display mode for video display #" << ii << ": " << SDL_GetError(); } else { - SDL_Log("Display #%d: display mode is %dx%dpx @ %dhz %s", ii, - current.w, current.h, current.refresh_rate, - get_pixel_format_string(current.format).c_str()); + message << "Display #" << ii << ": display mode is " << current.w << "x" << current.h << "px @ " << + current.refresh_rate << "hz " << get_pixel_format_string(current.format); } + log(message.str()); } } @@ -716,3 +760,8 @@ void Game::quit() Mix_Quit(); SDL_Quit(); } + +Game::~Game() +{ + get_delegate().unsubscribe(this); +} diff --git a/src/Game.hpp b/src/Game.hpp index 77c773d..0ab1f88 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #define SDL_MAIN_HANDLED #include "SDL.h" @@ -29,9 +30,10 @@ #include "Configuration.hpp" #include "Delegate.hpp" #include "Recorder.hpp" -#include "extension.hpp" #include "Sprite.hpp" #include "Audio.hpp" +#include "filesystem.hpp" +#include "extension.hpp" struct FramerateIndicator : Sprite { @@ -59,8 +61,8 @@ public: static const int DEFAULT_SDL_LOG_CATEGORY = SDL_LOG_CATEGORY_CUSTOM; SDL_Window* window; - SDL_Renderer* renderer = NULL; - SDL_GLContext glcontext = NULL; + SDL_Renderer* renderer = nullptr; + SDL_GLContext glcontext = nullptr; int frame_count_this_second = 0, framerate, ticks, last_frame_length; float frame_length = 1000.0 / 60.0, frame_time_overflow = 0, last_frame_timestamp, last_frame_count_timestamp, emscripten_previous_time; @@ -76,18 +78,18 @@ public: FramerateIndicator framerate_indicator = FramerateIndicator(this); Game(); - ~Game(); virtual void reset() { activate(); } void print_error(const std::string&); void print_sdl_error(const std::string&); - void print_gl_attributes(); void print_frame_length_history(); void load_sdl_context(); void load_gl_context(); + GLuint load_shader(const fs::path&, GLenum) const; + bool link_shader(GLuint program) const; void log(const std::string&, const int = DEFAULT_SDL_LOG_CATEGORY) const; void debug(const std::string&, const int = DEFAULT_SDL_LOG_CATEGORY) const; void log_renderer_info(SDL_RendererInfo&); - bool log_gl_errors(std::string); + bool log_gl_errors(std::string = ""); void log_display_mode(); void log_surface_format(SDL_Surface*, std::string = "surface"); std::string get_pixel_format_string(Uint32); @@ -107,6 +109,7 @@ public: void handle_quit_event(SDL_Event&); void quit(); virtual std::string get_class_name() const { return "Game"; } + ~Game(); template float weight(T amount) diff --git a/src/Recorder.cpp b/src/Recorder.cpp index 5a48b86..a1c57d2 100644 --- a/src/Recorder.cpp +++ b/src/Recorder.cpp @@ -323,25 +323,26 @@ void Recorder::finish_writing_video() { write_mp4(); } - std::cout << "Wrote video frames to " << current_video_directory.string() << - std::endl; + std::cout << "Wrote video frames to " << current_video_directory.string() << std::endl; writing_recording = false; } +/* Launch a system command that calls ffmpeg to write an x264 encoded MP4 from the image frames written. + * This requires ffmpeg to be installed on the user's system. Might only work on Linux (?) */ void Recorder::write_mp4() { glm::ivec2 size = get_display().get_window_size(); - std::stringstream mp4_command; - std::string pixel_format = - get_configuration()["recording"]["mp4-pixel-format"].get(); + std::ostringstream mp4_command; + std::string pixel_format = get_configuration()["recording"]["mp4-pixel-format"].get(); fs::path images_match = current_video_directory / "%05d.png"; mp4_command << "ffmpeg -f s16le -ac 2 -ar 22050 -i " << current_audio_path.string() << " -f image2 -framerate " << (1000 / get_frame_length()) << " -i " << images_match.string() << " -s " << size.x << "x" << size.y << " -c:v libx264 -crf 17 -pix_fmt " << pixel_format << " " << current_video_directory.string() << ".mp4"; - std::cout << mp4_command.str() << std::endl; - std::system(mp4_command.str().c_str()); + std::string mp4_command_str = mp4_command.str(); + std::cout << mp4_command_str << std::endl; + std::system(mp4_command_str.c_str()); } void Recorder::write_audio(Uint8* stream, int len) diff --git a/src/extension.cpp b/src/extension.cpp index 67ae794..a9745cd 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -1,7 +1,3 @@ -#include - -#include "sdl2-gfx/SDL2_gfxPrimitives.h" - #include "Pixels.hpp" #include "extension.hpp" @@ -571,6 +567,37 @@ fs::path sfw::get_next_file_name( return path; } +/* Read the file at path into a string and return the string */ +std::string sfw::file_to_string(const fs::path& path) +{ + std::fstream file; + file.open(path); + std::ostringstream message; + std::string m_str; + if (!file.is_open()) + { + message << "failed to open " << path; + message.str(); + SDL_Log("%s", m_str.c_str()); + return ""; + } + else + { + message << "opened file " << path; + m_str = message.str(); + SDL_Log("%s", m_str.c_str()); + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + std::string contents; + contents.resize(size + 1, '\0'); + file.seekg(0, std::ios::beg); + file.read(contents.data(), size); + contents[size] = '\0'; + SDL_LogDebug(SDL_LOG_CATEGORY_CUSTOM, "%s", contents.c_str()); + return contents; + } +} + void sfw::print_error(const std::string& message) { std::cerr << message << std::endl; diff --git a/src/extension.hpp b/src/extension.hpp index 8959f67..f2c349c 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "SDL.h" #include "SDL_image.h" @@ -60,8 +62,8 @@ namespace sfw SDL_Texture* get_pixel_scaled_texture(SDL_Renderer*, SDL_Texture*, int = 1, int = scaler::scale2x); SDL_Surface* get_surface_from_pixels(Pixels&); std::vector glob(fs::path); - fs::path get_next_file_name( - fs::path, int = 0, std::string = "", std::string = ""); + fs::path get_next_file_name(fs::path, int = 0, std::string = "", std::string = ""); + std::string file_to_string(const fs::path&); void print_error(const std::string&); void print_sdl_error(const std::string&);