started log class

This commit is contained in:
frank 2021-10-02 19:21:07 -04:00
parent f03d58dae1
commit f70ea1c215
22 changed files with 362 additions and 240 deletions

View File

@ -150,7 +150,7 @@ void Configuration::refresh()
{ {
std::ostringstream message; std::ostringstream message;
message << "config file modified, reloading " << config_path; message << "config file modified, reloading " << config_path;
debug(message.str()); sb::Log::log(message, sb::Log::DEBUG);
load(); load();
} }
} }

View File

@ -5,6 +5,7 @@
#include "filesystem.hpp" #include "filesystem.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Animation.hpp" #include "Animation.hpp"
#include "Log.hpp"
class Configuration : public Node class Configuration : public Node
{ {

View File

@ -1,5 +1,4 @@
#include "Display.hpp" #include "Display.hpp"
#include "Game.hpp"
/* Create a Display instance and subscribe to commands */ /* Create a Display instance and subscribe to commands */
Display::Display(Node* parent) : Node(parent) Display::Display(Node* parent) : Node(parent)
@ -28,7 +27,9 @@ Uint32 Display::pixel_format(int display_index) const
SDL_DisplayMode display_mode; SDL_DisplayMode display_mode;
if (SDL_GetCurrentDisplayMode(display_index, &display_mode) != 0) if (SDL_GetCurrentDisplayMode(display_index, &display_mode) != 0)
{ {
SDL_Log("could not get display mode for index %i: %s", display_index, SDL_GetError()); std::ostringstream message;
message << "could not get display mode for index " << display_index;
sb::Log::sdl_error(message.str());
return SDL_PIXELFORMAT_UNKNOWN; return SDL_PIXELFORMAT_UNKNOWN;
} }
else else
@ -123,12 +124,12 @@ void Display::toggle_fullscreen() const
SDL_Window* window = const_cast<SDL_Window*>(get_window()); SDL_Window* window = const_cast<SDL_Window*>(get_window());
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN)
{ {
log("fullscreen requested"); sb::Log::log("fullscreen requested");
SDL_SetWindowFullscreen(window, 0); SDL_SetWindowFullscreen(window, 0);
} }
else else
{ {
log("exit fullscreen requested"); sb::Log::log("exit fullscreen requested");
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
} }
} }

View File

@ -1,17 +1,15 @@
#ifndef Display_h_ #ifndef Display_h_
#define Display_h_ #define Display_h_
#define GLM_ENABLE_EXPERIMENTAL #include <sstream>
#include "glm/vec2.hpp" #include "glm/vec2.hpp"
#include "SDL.h" #include "SDL.h"
#include "SDL_image.h"
#include <SDL_image.h>
#include "sdl2-gfx/SDL2_gfxPrimitives.h" #include "sdl2-gfx/SDL2_gfxPrimitives.h"
#include "sdl2-gfx/SDL2_rotozoom.h" #include "sdl2-gfx/SDL2_rotozoom.h"
#include "Node.hpp" #include "Node.hpp"
#include "Box.hpp" #include "Box.hpp"
#include "Log.hpp"
class Display : public Node class Display : public Node
{ {
@ -32,4 +30,6 @@ public:
}; };
#include "Game.hpp"
#endif #endif

View File

@ -1,3 +1,15 @@
/* /\ +--------------------------------------------------------------+
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - originally created at [http://nugget.fun] |
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+
*/
#include "GLObject.hpp" #include "GLObject.hpp"
/* The deleter function is used for freeing the memory allocated to the object (for example, glDeleteTextures, /* The deleter function is used for freeing the memory allocated to the object (for example, glDeleteTextures,
@ -12,6 +24,9 @@ void GLObject::generate(generator_function generator)
GLuint id; GLuint id;
generator(1, &id); generator(1, &id);
this->id(id); this->id(id);
std::ostringstream message;
message << "Generated ID " << this->id() << " for GL object";
sb::Log::log(message, sb::Log::DEBUG);
} }
/* Set the shared pointer to point to a new GLuint with specified ID value */ /* Set the shared pointer to point to a new GLuint with specified ID value */

View File

@ -23,10 +23,6 @@
#ifndef GLObject_h_ #ifndef GLObject_h_
#define GLObject_h_ #define GLObject_h_
#include <iostream>
#include <memory>
#include <functional>
/* include Open GL */ /* include Open GL */
#if defined(__EMSCRIPTEN__) #if defined(__EMSCRIPTEN__)
#include <GL/glew.h> #include <GL/glew.h>
@ -34,6 +30,12 @@
#include "glew/glew.h" #include "glew/glew.h"
#endif #endif
#include <iostream>
#include <sstream>
#include <memory>
#include <functional>
#include "Log.hpp"
class GLObject class GLObject
{ {

View File

@ -1,44 +1,5 @@
#include "Game.hpp" #include "Game.hpp"
FramerateIndicator::FramerateIndicator(Node* parent) : Sprite(parent)
{
get_delegate().subscribe(&FramerateIndicator::respond, this);
hide();
}
void FramerateIndicator::respond(SDL_Event& event)
{
if (get_delegate().compare(event, "toggle-framerate"))
{
toggle_hidden();
}
}
SDL_Surface* FramerateIndicator::get_surface()
{
std::string padded = sb::pad(get_root()->frame_count_this_second, 2);
SDL_Surface* shaded = TTF_RenderText_Shaded(
get_root()->bp_mono_font, padded.c_str(), {0, 0, 0, 255}, {255, 255, 255, 255});
if (!shaded)
{
get_root()->print_sdl_error("Could not create text");
}
return shaded;
}
void FramerateIndicator::refresh()
{
if (!is_hidden() && get_root()->bp_mono_font != nullptr)
{
unload();
SDL_Surface* surface = get_surface();
SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface);
add_frames(texture);
SDL_FreeSurface(surface);
set_ne(get_display().window_box().ne());
}
}
Game::Game() Game::Game()
{ {
/* Set the appropriate priority level for the default log category so either info level messages /* Set the appropriate priority level for the default log category so either info level messages
@ -52,13 +13,13 @@ Game::Game()
{ {
default_log_category_priority = SDL_LOG_PRIORITY_INFO; default_log_category_priority = SDL_LOG_PRIORITY_INFO;
} }
SDL_LogSetPriority(DEFAULT_SDL_LOG_CATEGORY, default_log_category_priority); SDL_LogSetPriority(sb::Log::DEFAULT_CATEGORY, default_log_category_priority);
/* set custom log function that 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); SDL_LogSetOutputFunction(&Game::sdl_log_override, this);
/* pretty print config to debug log */ /* pretty print config to debug log */
std::ostringstream log_message; std::ostringstream log_message;
log_message << std::setw(4) << get_configuration() << std::endl; log_message << std::setw(4) << get_configuration() << std::endl;
debug(log_message.str()); sb::Log::log(log_message, sb::Log::DEBUG);
/* tell SDL which render driver you will be requesting when calling SDL_CreateRenderer */ /* 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<std::string>().c_str()); SDL_SetHint(SDL_HINT_RENDER_DRIVER, get_configuration()["display"]["render driver"].get<std::string>().c_str());
/* initialize the buffer of frame lengths which will be used to calculate FPS */ /* initialize the buffer of frame lengths which will be used to calculate FPS */
@ -77,17 +38,17 @@ Game::Game()
SDL_GetVersion(&version); SDL_GetVersion(&version);
log_message << "linked to SDL " << static_cast<int>(version.major) << "." << static_cast<int>(version.minor) << "." << log_message << "linked to SDL " << static_cast<int>(version.major) << "." << static_cast<int>(version.minor) << "." <<
static_cast<int>(version.patch); static_cast<int>(version.patch);
log(log_message.str()); sb::Log::log(log_message);
/* allows use of our own main function (?) see SDL_SetMainReady.html */ /* allows use of our own main function (?) see SDL_SetMainReady.html */
SDL_SetMainReady(); SDL_SetMainReady();
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
{ {
print_sdl_error("SDL could not initialize"); sb::Log::sdl_error("SDL could not initialize");
flag_to_end(); flag_to_end();
} }
log_message = std::ostringstream(); log_message = std::ostringstream();
log_message << "GLEW " << glewGetString(GLEW_VERSION); log_message << "GLEW " << glewGetString(GLEW_VERSION);
log(log_message.str()); sb::Log::log(log_message.str());
glm::ivec2 window_size = get_configuration()["display"]["dimensions"].get<glm::ivec2>(); glm::ivec2 window_size = get_configuration()["display"]["dimensions"].get<glm::ivec2>();
/* Create a window with dimensions set in the config, centered, and flagged to be usable in OpenGL context */ /* Create a window with dimensions set in the config, centered, and flagged to be usable in OpenGL context */
window = SDL_CreateWindow( window = SDL_CreateWindow(
@ -95,7 +56,7 @@ Game::Game()
SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, SDL_WINDOW_OPENGL); SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, SDL_WINDOW_OPENGL);
if (window == nullptr) if (window == nullptr)
{ {
print_sdl_error("Could not create window"); sb::Log::sdl_error("Could not create window");
flag_to_end(); flag_to_end();
} }
/* Create an SDL renderer for clearing the screen to black and for logging renderer properties. Destroy renderer /* Create an SDL renderer for clearing the screen to black and for logging renderer properties. Destroy renderer
@ -103,7 +64,7 @@ Game::Game()
*/ */
if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr) if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr)
{ {
print_sdl_error("Could not create renderer"); sb::Log::sdl_error("Could not create renderer");
flag_to_end(); flag_to_end();
} }
else else
@ -113,7 +74,7 @@ Game::Game()
SDL_GetRendererOutputSize(renderer, &w, &h); SDL_GetRendererOutputSize(renderer, &w, &h);
log_message = std::ostringstream(); log_message = std::ostringstream();
log_message << "renderer output size is " << w << "x" << h; log_message << "renderer output size is " << w << "x" << h;
log(log_message.str()); sb::Log::log(log_message);
/* clear screen to black */ /* clear screen to black */
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer, nullptr);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
@ -125,7 +86,7 @@ Game::Game()
SDL_ShowCursor(get_configuration()["display"]["show-cursor"]); SDL_ShowCursor(get_configuration()["display"]["show-cursor"]);
if (TTF_Init() < 0) if (TTF_Init() < 0)
{ {
print_sdl_error("Could not initialize SDL ttf"); sb::Log::sdl_error("Could not initialize SDL ttf");
flag_to_end(); flag_to_end();
} }
else else
@ -135,11 +96,11 @@ Game::Game()
} }
if ((bp_mono_font = TTF_OpenFont("BPmono.ttf", 14)) == nullptr) if ((bp_mono_font = TTF_OpenFont("BPmono.ttf", 14)) == nullptr)
{ {
print_error("Could not load BPmono.ttf"); sb::Log::log("Could not load BPmono.ttf", sb::Log::ERROR);
} }
if (Mix_Init(MIX_INIT_OGG) == 0) if (Mix_Init(MIX_INIT_OGG) == 0)
{ {
print_sdl_error("Could not initialize SDL mixer"); sb::Log::sdl_error("Could not initialize SDL mixer");
flag_to_end(); flag_to_end();
} }
else else
@ -151,20 +112,22 @@ Game::Game()
// MIX_DEFAULT_CHANNELS, 1024) < 0) // MIX_DEFAULT_CHANNELS, 1024) < 0)
if (Mix_OpenAudio(11025, AUDIO_U8, MIX_DEFAULT_CHANNELS, 2048) < 0) if (Mix_OpenAudio(11025, AUDIO_U8, MIX_DEFAULT_CHANNELS, 2048) < 0)
{ {
print_sdl_error("Could not set up audio"); sb::Log::sdl_error("Could not set up audio");
} }
SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver()); SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
const int audio_device_count = SDL_GetNumAudioDevices(SDL_TRUE); const int audio_device_count = SDL_GetNumAudioDevices(SDL_TRUE);
for (int ii = 0; ii < audio_device_count; ii++) for (int ii = 0; ii < audio_device_count; ii++)
{ {
SDL_Log("Found audio capture device %i: %s", ii, SDL_GetAudioDeviceName(ii, SDL_TRUE)); std::ostringstream message;
message << "Found audio capture device " << ii << ": " << SDL_GetAudioDeviceName(ii, SDL_TRUE);
sb::Log::log(message);
} }
audio.load_sfx(); audio.load_sfx();
audio.load_bgm(); audio.load_bgm();
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
log("big endian"); sb::Log::log("big endian");
#else #else
log("little endian"); sb::Log::log("little endian");
#endif #endif
last_frame_timestamp = SDL_GetTicks(); last_frame_timestamp = SDL_GetTicks();
} }
@ -186,7 +149,7 @@ void Game::load_sdl_context()
} }
if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr) if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED)) == nullptr)
{ {
print_sdl_error("Could not create renderer"); sb::Log::sdl_error("Could not create renderer");
flag_to_end(); flag_to_end();
} }
else else
@ -216,46 +179,45 @@ void Game::load_gl_context()
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
if ((glcontext = SDL_GL_CreateContext(window)) == nullptr) if ((glcontext = SDL_GL_CreateContext(window)) == nullptr)
{ {
print_sdl_error("Could not get GL context"); sb::Log::sdl_error("Could not get GL context");
flag_to_end(); flag_to_end();
} }
/* try enabling vsync */ /* try enabling vsync */
if (SDL_GL_SetSwapInterval(1) == 0) if (SDL_GL_SetSwapInterval(1) == 0)
{ {
log("enabled vsync"); sb::Log::log("enabled vsync");
} }
else else
{ {
log("vsync not supported"); sb::Log::log("vsync not supported");
} }
GLenum error = glewInit(); GLenum error = glewInit();
std::ostringstream message; std::ostringstream message;
if (error != GLEW_OK) if (error != GLEW_OK)
{ {
message << "GLEW could not initialize " << glewGetErrorString(error); message << "GLEW could not initialize " << glewGetErrorString(error);
print_error(message.str()); sb::Log::log(message, sb::Log::ERROR);
} }
message << "OpenGL " << glGetString(GL_VERSION) << ", renderer " << glGetString(GL_RENDERER) << ", shading language " << message << "OpenGL " << glGetString(GL_VERSION) << ", renderer " << glGetString(GL_RENDERER) << ", shading language " <<
glGetString(GL_SHADING_LANGUAGE_VERSION); glGetString(GL_SHADING_LANGUAGE_VERSION);
log(message.str()); sb::Log::log(message);
is_gl_context = true; is_gl_context = true;
log_display_mode(); log_display_mode();
} }
/* Overrides SDL's default log function to log a message to stdout/stderr and, if log is enabled in the /* Overrides SDL's default log function to log a message to stdout/stderr and, if log is enabled in the
* global configuration, to a file. Debug level statements may be suppressed, printed to stdout, or printed to * global configuration, to a file. Debug level statements may be suppressed, printed to stdout, or printed to
* both stdout and file, depending on the global configuration. * both stdout and file, depending on the global configuration. */
*/
void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priority, const char* message) void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priority, const char* message)
{ {
Game* game = static_cast<Game*>(userdata); Game* game = static_cast<Game*>(userdata);
std::ostream& out = (priority > SDL_LOG_PRIORITY_WARN) ? std::cerr : std::cout; std::ostream& out = (priority > SDL_LOG_PRIORITY_WARN) ? std::cerr : std::cout;
// print to stdout/stderr if priority is higher than debug or debug statements are enabled /* print to stdout/stderr if priority is higher than debug or debug statements are enabled */
if (priority > SDL_LOG_PRIORITY_DEBUG || game->get_configuration()["log"]["debug-to-stdout"]) if (priority > SDL_LOG_PRIORITY_DEBUG || game->get_configuration()["log"]["debug-to-stdout"])
{ {
out << message << std::endl; out << message << std::endl;
} }
// handle writing to log file /* handle writing to log file */
if (game->get_configuration()["log"]["enabled"]) if (game->get_configuration()["log"]["enabled"])
{ {
fs::path path = game->get_configuration()["log"]["output-directory"]; fs::path path = game->get_configuration()["log"]["output-directory"];
@ -263,18 +225,18 @@ void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priori
{ {
fs::create_directories(path); fs::create_directories(path);
} }
// prepend a timestamp to the message /* prepend a timestamp to the message */
std::time_t now = std::time(nullptr); std::time_t now = std::time(nullptr);
std::stringstream stamped_message; std::stringstream stamped_message;
stamped_message << std::put_time(std::localtime(&now), "%F %T ") << message; stamped_message << std::put_time(std::localtime(&now), "%F %T ") << message;
// if debug is enabled, append message to debug log file /* if debug is enabled, append message to debug log file */
if (game->get_configuration()["log"]["debug-to-file"]) if (game->get_configuration()["log"]["debug-to-file"])
{ {
fs::path debug_path = path / game->get_configuration()["log"]["debug-file-name"]; fs::path debug_path = path / game->get_configuration()["log"]["debug-file-name"];
std::ofstream debug_stream(debug_path, std::ios_base::app); std::ofstream debug_stream(debug_path, std::ios_base::app);
debug_stream << stamped_message.str() << std::endl; debug_stream << stamped_message.str() << std::endl;
} }
// only append messages to the info log that are higher than debug priority /* only append messages to the info log that are higher than debug priority */
if (priority > SDL_LOG_PRIORITY_DEBUG) if (priority > SDL_LOG_PRIORITY_DEBUG)
{ {
fs::path info_path = path / game->get_configuration()["log"]["info-file-name"]; fs::path info_path = path / game->get_configuration()["log"]["info-file-name"];
@ -284,16 +246,6 @@ void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priori
} }
} }
void Game::print_error(const std::string& message)
{
sb::print_error(message);
}
void Game::print_sdl_error(const std::string& message)
{
sb::print_sdl_error(message);
}
void Game::print_frame_length_history() void Game::print_frame_length_history()
{ {
for (float& frame_length : frame_length_history) for (float& frame_length : frame_length_history)
@ -318,7 +270,7 @@ GLuint Game::load_shader(const fs::path& path, GLenum type) const
if (is_compiled == GL_TRUE) if (is_compiled == GL_TRUE)
{ {
message << "compiled shader at " << path; message << "compiled shader at " << path;
log(message.str()); sb::Log::log(message);
return shader; return shader;
} }
else else
@ -330,7 +282,7 @@ GLuint Game::load_shader(const fs::path& path, GLenum type) const
error_info.resize(max_length, 0); error_info.resize(max_length, 0);
glGetShaderInfoLog(shader, error_info.size(), nullptr, error_info.data()); glGetShaderInfoLog(shader, error_info.size(), nullptr, error_info.data());
message << "failed to compile " << path << ": " << error_info; message << "failed to compile " << path << ": " << error_info;
log(message.str()); sb::Log::log(message, sb::Log::Level::ERROR);
return -1; return -1;
} }
} }
@ -344,7 +296,7 @@ bool Game::link_shader(GLuint program) const
if (is_linked == GL_TRUE) if (is_linked == GL_TRUE)
{ {
message << "linked shader program " << program; message << "linked shader program " << program;
log(message.str()); sb::Log::log(message);
return true; return true;
} }
else else
@ -356,81 +308,18 @@ bool Game::link_shader(GLuint program) const
error_info.resize(max_length, 0); error_info.resize(max_length, 0);
glGetProgramInfoLog(program, error_info.size(), nullptr, error_info.data()); glGetProgramInfoLog(program, error_info.size(), nullptr, error_info.data());
message << "failed linking shader program " << program << ": " << error_info; message << "failed linking shader program " << program << ": " << error_info;
log(message.str()); sb::Log::log(message, sb::Log::Level::ERROR);
return false; return false;
} }
} }
/* Send an info priority message to SDL's log output function, which is overridden by our own member
* function. Category will default to SDL's custom category.
*/
void Game::log(const std::string& message, const int category)
{
SDL_LogInfo(category, "%s", message.c_str());
}
/* Send a debug priority message to SDL's log output function, which is overridden by our own member
* function. Category will default to SDL's custom category. Using the default category will ensure
* that debug level statements are handled according to the options in the global configuration.
*/
void Game::debug(const std::string& message, const int category)
{
SDL_LogDebug(category, "%s", message.c_str());
}
void Game::log_renderer_info(SDL_RendererInfo& info) void Game::log_renderer_info(SDL_RendererInfo& info)
{ {
SDL_Log("renderer name: %s, flags: %i, texture formats: %i, " std::ostringstream message;
"max texture w: %i, max texture h: %i", info.name, info.flags, message << "renderer name: " << info.name << ", flags: " << info.flags << ", texture formats: " <<
info.num_texture_formats, info.max_texture_width, info.num_texture_formats << ", max texture w: " << info.max_texture_width << ", max texture h: " <<
info.max_texture_height); info.max_texture_height;
} sb::Log::log(message);
bool Game::log_gl_errors(std::string suffix)
{
GLenum error;
bool error_logged = false;
while ((error = glGetError()) != GL_NO_ERROR)
{
error_logged = true;
std::ostringstream message;
if (error == GL_INVALID_ENUM)
{
message << "GL_INVALID_ENUM, an unacceptable value is specified for an enumerated argument";
}
else if (error == GL_INVALID_VALUE)
{
message << "GL_INVALID_VALUE, a numeric argument is out of range";
}
else if (error == GL_INVALID_OPERATION)
{
message << "GL_INVALID_OPERATION, the specified operation is not allowed in the current state";
}
else if (error == GL_INVALID_FRAMEBUFFER_OPERATION)
{
message << "GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is not complete";
}
else if (error == GL_OUT_OF_MEMORY)
{
message << "GL_OUT_OF_MEMORY, there is not enough memory left to execute the command";
}
else if (error == GL_STACK_UNDERFLOW)
{
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)
{
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;
} }
/* Write resolution, monitor refresh rate, and pixel format to the log. Code taken from SDL_GetCurrentDisplayMode.html /* Write resolution, monitor refresh rate, and pixel format to the log. Code taken from SDL_GetCurrentDisplayMode.html
@ -444,14 +333,15 @@ void Game::log_display_mode()
int mode = SDL_GetCurrentDisplayMode(ii, &current); int mode = SDL_GetCurrentDisplayMode(ii, &current);
if (mode != 0) if (mode != 0)
{ {
message << "Could not get display mode for video display #" << ii << ": " << SDL_GetError(); message << "Could not get display mode for video display #" << ii;
sb::Log::sdl_error(message.str());
} }
else else
{ {
message << "Display #" << ii << ": display mode is " << current.w << "x" << current.h << "px @ " << message << "Display #" << ii << ": display mode is " << current.w << "x" << current.h << "px @ " <<
current.refresh_rate << "hz " << get_pixel_format_string(current.format); current.refresh_rate << "hz " << get_pixel_format_string(current.format);
sb::Log::log(message);
} }
log(message.str());
} }
} }
@ -772,3 +662,42 @@ Game::~Game()
{ {
get_delegate().unsubscribe(this); get_delegate().unsubscribe(this);
} }
FramerateIndicator::FramerateIndicator(Node* parent) : Sprite(parent)
{
get_delegate().subscribe(&FramerateIndicator::respond, this);
hide();
}
void FramerateIndicator::respond(SDL_Event& event)
{
if (get_delegate().compare(event, "toggle-framerate"))
{
toggle_hidden();
}
}
SDL_Surface* FramerateIndicator::get_surface()
{
std::string padded = sb::pad(get_root()->frame_count_this_second, 2);
SDL_Surface* shaded = TTF_RenderText_Shaded(
get_root()->bp_mono_font, padded.c_str(), {0, 0, 0, 255}, {255, 255, 255, 255});
if (!shaded)
{
sb::Log::sdl_error("Could not create text");
}
return shaded;
}
void FramerateIndicator::refresh()
{
if (!is_hidden() && get_root()->bp_mono_font != nullptr)
{
unload();
SDL_Surface* surface = get_surface();
SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface);
add_frames(texture);
SDL_FreeSurface(surface);
set_ne(get_display().window_box().ne());
}
}

View File

@ -32,6 +32,7 @@
#include "Recorder.hpp" #include "Recorder.hpp"
#include "Sprite.hpp" #include "Sprite.hpp"
#include "Audio.hpp" #include "Audio.hpp"
#include "Log.hpp"
#include "filesystem.hpp" #include "filesystem.hpp"
#include "extension.hpp" #include "extension.hpp"
@ -71,7 +72,6 @@ public:
Game(Game&&) = delete; Game(Game&&) = delete;
Game& operator=(Game&&) = delete; Game& operator=(Game&&) = delete;
static const int DEFAULT_SDL_LOG_CATEGORY = SDL_LOG_CATEGORY_CUSTOM;
SDL_Window* window; SDL_Window* window;
SDL_Renderer* renderer = nullptr; SDL_Renderer* renderer = nullptr;
SDL_GLContext glcontext = nullptr; SDL_GLContext glcontext = nullptr;
@ -90,17 +90,12 @@ public:
Game(); Game();
virtual void reset() { activate(); } virtual void reset() { activate(); }
void print_error(const std::string&);
void print_sdl_error(const std::string&);
void print_frame_length_history(); void print_frame_length_history();
void load_sdl_context(); void load_sdl_context();
void load_gl_context(); void load_gl_context();
GLuint load_shader(const fs::path&, GLenum) const; GLuint load_shader(const fs::path&, GLenum) const;
bool link_shader(GLuint program) const; bool link_shader(GLuint program) const;
static void log(const std::string&, const int = DEFAULT_SDL_LOG_CATEGORY);
static void debug(const std::string&, const int = DEFAULT_SDL_LOG_CATEGORY);
void log_renderer_info(SDL_RendererInfo&); void log_renderer_info(SDL_RendererInfo&);
static bool log_gl_errors(std::string = "");
void log_display_mode(); void log_display_mode();
void log_surface_format(SDL_Surface*, std::string = "surface"); void log_surface_format(SDL_Surface*, std::string = "surface");
std::string get_pixel_format_string(Uint32); std::string get_pixel_format_string(Uint32);

123
src/Log.cpp Normal file
View File

@ -0,0 +1,123 @@
/* /\ +--------------------------------------------------------------+
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - originally created at [http://nugget.fun] |
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+ */
#include "Log.hpp"
/* Send a message to SDL's log function, which currently gets overridden in the Game class.
* The default level is INFO. Category will default to SDL's custom category. Using the default
* category will ensure that debug level statements are handled according to the options in the
* global configuration. */
void sb::Log::log(const std::string& message, const Level level, const int category)
{
SDL_LogMessage(category, static_cast<SDL_LogPriority>(level), "%s", message.c_str());
}
/* Convert string stream to string and forward */
void sb::Log::log(const std::ostringstream& message, const Level level, const int category)
{
log(message.str(), level, category);
}
/* Log all GL errors accumulated since the last time this function was called */
bool sb::Log::gl_errors(const std::string& suffix)
{
GLenum error;
bool error_logged = false;
while ((error = glGetError()) != GL_NO_ERROR)
{
error_logged = true;
std::ostringstream message;
if (error == GL_INVALID_ENUM)
{
message << "GL_INVALID_ENUM, an unacceptable value is specified for an enumerated argument";
}
else if (error == GL_INVALID_VALUE)
{
message << "GL_INVALID_VALUE, a numeric argument is out of range";
}
else if (error == GL_INVALID_OPERATION)
{
message << "GL_INVALID_OPERATION, the specified operation is not allowed in the current state";
}
else if (error == GL_INVALID_FRAMEBUFFER_OPERATION)
{
message << "GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is not complete";
}
else if (error == GL_OUT_OF_MEMORY)
{
message << "GL_OUT_OF_MEMORY, there is not enough memory left to execute the command";
}
else if (error == GL_STACK_UNDERFLOW)
{
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)
{
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);
}
return error_logged;
}
void sb::Log::sdl_error(const std::string& original_message)
{
std::ostringstream message;
message << original_message << " " << SDL_GetError();
log(message, Level::ERROR);
}
/* Overrides SDL's default log function to log a message to stdout/stderr and, if log is enabled in the
* global configuration, to a file. Debug level statements may be suppressed, printed to stdout, or printed to
* both stdout and file, depending on the global configuration.
*/
// void sb::Log::record(void* userdata, int category, SDL_LogPriority priority, const char* message)
// {
// Game* game = static_cast<Game*>(userdata);
// std::ostream& out = (priority > SDL_LOG_PRIORITY_WARN) ? std::cerr : std::cout;
// /* print to stdout/stderr if priority is higher than debug or debug statements are enabled */
// if (priority > SDL_LOG_PRIORITY_DEBUG /* || game->get_configuration()["log"]["debug-to-stdout"] */)
// {
// out << message << std::endl;
// }
// /* handle writing to log file */
// if (game->get_configuration()["log"]["enabled"])
// {
// fs::path path = game->get_configuration()["log"]["output-directory"];
// if (!fs::exists(path))
// {
// fs::create_directories(path);
// }
// /* prepend a timestamp to the message */
// std::time_t now = std::time(nullptr);
// std::stringstream stamped_message;
// stamped_message << std::put_time(std::localtime(&now), "%F %T ") << message;
// /* if debug is enabled, append message to debug log file */
// if (game->get_configuration()["log"]["debug-to-file"])
// {
// fs::path debug_path = path / game->get_configuration()["log"]["debug-file-name"];
// std::ofstream debug_stream(debug_path, std::ios_base::app);
// debug_stream << stamped_message.str() << std::endl;
// }
// /* only append messages to the info log that are higher than debug priority */
// if (priority > SDL_LOG_PRIORITY_DEBUG)
// {
// fs::path info_path = path / game->get_configuration()["log"]["info-file-name"];
// std::ofstream info_stream(info_path, std::ios_base::app);
// info_stream << stamped_message.str() << std::endl;
// }
// }
// }

72
src/Log.hpp Normal file
View File

@ -0,0 +1,72 @@
/* /\ +--------------------------------------------------------------+
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - originally created at [http://nugget.fun] |
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+
[Log.hpp]
Log messages of specified priority to the SDL logging method, which is overridden in
the Game class to write to stdout, file, or both, depending on the user's configuration
settings.
The logging methods can be used statically, or the log object defined here can be used
like a stream to stream messages to.
*/
#ifndef Log_h_
#define Log_h_
/* include Open GL */
#if defined(__EMSCRIPTEN__)
#include <GL/glew.h>
#else
#include "glew/glew.h"
#endif
#include <iostream>
#include <sstream>
#include <functional>
#include <SDL.h>
/* #include "filesystem.hpp" */
namespace sb
{
class Log
{
public:
/* These definitions are equivalent to SDL's SDL_LOG_PRIORITY_* values */
enum Level
{
VERBOSE = 1,
DEBUG,
INFO,
WARN,
ERROR,
CRITICAL,
};
static const int DEFAULT_CATEGORY = SDL_LOG_CATEGORY_CUSTOM;
Log(std::function<void(void*, int, SDL_LogPriority, const char*)>);
static void log(const std::string&, const Level = INFO, const int = DEFAULT_CATEGORY);
static void log(const std::ostringstream&, const Level = INFO, const int = DEFAULT_CATEGORY);
static bool gl_errors(const std::string& = "");
static void sdl_error(const std::string&);
/* static void record(void*, int, SDL_LogPriority, const char*); */
};
/* Log log = Log(&Log::record); */
}
#endif

View File

@ -11,7 +11,7 @@ Node::Node() : Node(nullptr) {}
Node::Node(Node* parent) : parent(parent) Node::Node(Node* parent) : parent(parent)
{ {
debug("constructing node " + get_branch_as_string()); sb::Log::log("constructing node " + get_branch_as_string(), sb::Log::DEBUG);
} }
void Node::set_parent(Node* other) void Node::set_parent(Node* other)
@ -124,16 +124,6 @@ void Node::unsuppress_input()
get_root()->get_input().unsuppress(); get_root()->get_input().unsuppress();
} }
void Node::log(const std::string& message) const
{
get_root()->log(message);
}
void Node::debug(const std::string& message) const
{
get_root()->debug(message);
}
const std::string Node::get_branch_as_string() const const std::string Node::get_branch_as_string() const
{ {
const Node* current = this; const Node* current = this;
@ -152,6 +142,6 @@ const std::string Node::get_branch_as_string() const
Node::~Node() Node::~Node()
{ {
debug("destroying node " + get_branch_as_string()); sb::Log::log("destroying node " + get_branch_as_string(), sb::Log::DEBUG);
get_delegate().unsubscribe(this); get_delegate().unsubscribe(this);
} }

View File

@ -6,6 +6,7 @@
#include "glm/vec2.hpp" #include "glm/vec2.hpp"
#include "json/json.hpp" #include "json/json.hpp"
#include "SDL.h" #include "SDL.h"
#include "Log.hpp"
#include "filesystem.hpp" #include "filesystem.hpp"
class Game; class Game;
@ -45,8 +46,6 @@ public:
void suppress_input(); void suppress_input();
void suppress_input_temporarily(int = 0); void suppress_input_temporarily(int = 0);
void unsuppress_input(); void unsuppress_input();
void log(const std::string&) const;
void debug(const std::string&) const;
const std::string get_branch_as_string() const; const std::string get_branch_as_string() const;
virtual std::string class_name() const { return "Node"; }; virtual std::string class_name() const { return "Node"; };
virtual ~Node(); virtual ~Node();

View File

@ -11,11 +11,11 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const Box& box) :
SDL_DisplayMode display_mode; SDL_DisplayMode display_mode;
if (SDL_GetCurrentDisplayMode(0, &display_mode) < 0) if (SDL_GetCurrentDisplayMode(0, &display_mode) < 0)
{ {
sb::print_sdl_error("could not get current display mode"); sb::Log::sdl_error("could not get current display mode");
} }
if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0)
{ {
sb::print_sdl_error("could not get renderer output size"); sb::Log::sdl_error("could not get renderer output size");
} }
format_enum = display_mode.format; format_enum = display_mode.format;
texture_access = TEXTURE_ACCESS_SCREEN; texture_access = TEXTURE_ACCESS_SCREEN;
@ -57,7 +57,7 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const Box& box) :
source = operator new(bytes_total); source = operator new(bytes_total);
if (SDL_RenderReadPixels(renderer, &rect, format->format, source, format->BytesPerPixel * rect.w) < 0) if (SDL_RenderReadPixels(renderer, &rect, format->format, source, format->BytesPerPixel * rect.w) < 0)
{ {
sb::print_sdl_error("could not read pixels"); sb::Log::sdl_error("could not read pixels");
operator delete(source); operator delete(source);
} }
else else
@ -74,12 +74,12 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const Box& box) :
int pitch; int pitch;
if (SDL_LockTexture(texture, &rect, &source, &pitch) < 0) if (SDL_LockTexture(texture, &rect, &source, &pitch) < 0)
{ {
sb::print_sdl_error("could not lock texture"); sb::Log::sdl_error("could not lock texture");
} }
} }
else else
{ {
sb::print_error("unknown texture format for loading pixels"); sb::Log::log("unknown texture format for loading pixels", sb::Log::Level::ERROR);
} }
} }

View File

@ -4,6 +4,7 @@
#include "SDL.h" #include "SDL.h"
#include "Box.hpp" #include "Box.hpp"
#include "Color.hpp" #include "Color.hpp"
#include "Log.hpp"
#include "extension.hpp" #include "extension.hpp"
class Sprite; class Sprite;

View File

@ -43,7 +43,7 @@ void Recorder::respond(SDL_Event& event)
} }
else else
{ {
SDL_Log("Writing in progress, cannot start recording"); sb::Log::log("Writing in progress, cannot start recording");
} }
} }
else if (get_delegate().compare(event, "save-current-stash")) else if (get_delegate().compare(event, "save-current-stash"))
@ -52,7 +52,9 @@ void Recorder::respond(SDL_Event& event)
} }
else if (get_delegate().compare(event, "print-video-memory-size")) else if (get_delegate().compare(event, "print-video-memory-size"))
{ {
SDL_Log("Video memory size is %iMB", get_memory_size()); std::ostringstream message;
message << "Video memory size is " << get_memory_size() << "MB";
sb::Log::log(message);
} }
} }
@ -74,7 +76,7 @@ void Recorder::capture_screen()
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
std::ostringstream message; std::ostringstream message;
message << "saved screenshot to " << path; message << "saved screenshot to " << path;
log(message.str()); sb::Log::log(message);
} }
/* Writes a video of what was just displayed on the screen up until the function was called. The length /* Writes a video of what was just displayed on the screen up until the function was called. The length
@ -87,7 +89,7 @@ void Recorder::grab_stash()
int length = get_configuration()["recording"]["max-stash-length"]; int length = get_configuration()["recording"]["max-stash-length"];
std::ostringstream message; std::ostringstream message;
message << "stashing most recent " << length / 1000.0f << " seconds of video"; message << "stashing most recent " << length / 1000.0f << " seconds of video";
log(message.str()); sb::Log::log(message);
most_recent_stash = current_stash; most_recent_stash = current_stash;
current_stash = Stash(); current_stash = Stash();
writing_recording = true; writing_recording = true;
@ -97,7 +99,7 @@ void Recorder::grab_stash()
} }
else else
{ {
log("recording in progress, cannot grab most recent frames"); sb::Log::log("recording in progress, cannot grab most recent frames");
} }
} }
@ -117,7 +119,9 @@ void Recorder::write_most_recent_frames()
{ {
write_mp4(); write_mp4();
} }
SDL_Log("wrote video frames to %s", current_video_directory.c_str()); std::ostringstream message;
message << "wrote video frames to " << current_video_directory;
sb::Log::log(message);
writing_recording = false; writing_recording = false;
} }
@ -125,7 +129,7 @@ void Recorder::start_recording()
{ {
if (!writing_recording) if (!writing_recording)
{ {
log("starting recording"); sb::Log::log("starting recording");
is_recording = true; is_recording = true;
video_stashes.push_back(Stash()); video_stashes.push_back(Stash());
make_directory(); make_directory();
@ -133,7 +137,7 @@ void Recorder::start_recording()
} }
else else
{ {
log("writing in progress, cannot start recording"); sb::Log::log("writing in progress, cannot start recording", sb::Log::WARN);
} }
} }

View File

@ -18,6 +18,7 @@
#include "filesystem.hpp" #include "filesystem.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "Animation.hpp" #include "Animation.hpp"
#include "Log.hpp"
struct Stash struct Stash
{ {

View File

@ -44,7 +44,7 @@ void Sprite::associate(std::string path)
{ {
std::ostringstream message; std::ostringstream message;
message << "invalid path " << path; message << "invalid path " << path;
get_root()->print_error(message.str()); sb::Log::log(message, sb::Log::Level::ERROR);
} }
} }
@ -78,7 +78,7 @@ void Sprite::load_file(fs::path path)
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, previous_scale_quality); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, previous_scale_quality);
if (not texture) if (not texture)
{ {
game->print_sdl_error("Could not load image"); sb::Log::sdl_error("Could not load image");
} }
else else
{ {

View File

@ -15,6 +15,7 @@
#include "Box.hpp" #include "Box.hpp"
#include "Animation.hpp" #include "Animation.hpp"
#include "Color.hpp" #include "Color.hpp"
#include "Log.hpp"
class Game; class Game;

View File

@ -30,7 +30,7 @@ void Texture::generate(glm::vec2 size)
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, size.x, size.y); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8, size.x, size.y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Game::log_gl_errors(); sb::Log::gl_errors();
} }
/* When called with no parameters, use the stored path variable */ /* When called with no parameters, use the stored path variable */
@ -65,7 +65,7 @@ void Texture::load(SDL_Surface* surface)
load(surface->pixels, {surface->w, surface->h}, GL_RGBA, GL_UNSIGNED_BYTE); load(surface->pixels, {surface->w, surface->h}, GL_RGBA, GL_UNSIGNED_BYTE);
std::ostringstream message; std::ostringstream message;
message << "loaded " << path << " (" << surface->w << "x" << surface->h << ")"; message << "loaded " << path << " (" << surface->w << "x" << surface->h << ")";
Game::log(message.str()); sb::Log::log(message);
} }
/* Bind texture and load pixel data using this class's generated ID */ /* Bind texture and load pixel data using this class's generated ID */
@ -77,7 +77,7 @@ void Texture::load(void* pixels, glm::vec2 size, GLenum format, GLenum type)
} }
bind(); bind();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.x, size.y, format, type, pixels); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.x, size.y, format, type, pixels);
Game::log_gl_errors(); sb::Log::gl_errors();
} }
/* The texture must have been previously generated with a size to use this generic pixel data load function */ /* The texture must have been previously generated with a size to use this generic pixel data load function */

View File

@ -23,12 +23,13 @@
#define Texture_h_ #define Texture_h_
#include <stdexcept> #include <stdexcept>
#include "glm/vec2.hpp"
#include "SDL.h" #include "SDL.h"
#include "SDL_image.h" #include "SDL_image.h"
#include "sdl2-gfx/SDL2_rotozoom.h" #include "sdl2-gfx/SDL2_rotozoom.h"
#include "filesystem.hpp" #include "filesystem.hpp"
#include "GLObject.hpp" #include "GLObject.hpp"
#include "Game.hpp" #include "Log.hpp"
/* include Open GL */ /* include Open GL */
#if defined(__EMSCRIPTEN__) #if defined(__EMSCRIPTEN__)

View File

@ -99,7 +99,7 @@ void sb::populate_pixel_2d_array(
int access; int access;
if (SDL_QueryTexture(texture, nullptr, &access, nullptr, nullptr) < 0) if (SDL_QueryTexture(texture, nullptr, &access, nullptr, nullptr) < 0)
{ {
print_sdl_error("Could not query texture for access flag"); sb::Log::sdl_error("Could not query texture for access flag");
} }
else else
{ {
@ -109,7 +109,7 @@ void sb::populate_pixel_2d_array(
} }
if (SDL_SetRenderTarget(renderer, texture) < 0) if (SDL_SetRenderTarget(renderer, texture) < 0)
{ {
print_sdl_error("Could not set render target"); sb::Log::sdl_error("Could not set render target");
} }
else else
{ {
@ -121,7 +121,7 @@ void sb::populate_pixel_2d_array(
SDL_Rect int_rect = region; SDL_Rect int_rect = region;
if (SDL_RenderReadPixels(renderer, &int_rect, format, source, bytes_per_row) < 0) if (SDL_RenderReadPixels(renderer, &int_rect, format, source, bytes_per_row) < 0)
{ {
print_sdl_error("Could not read pixels after setting remapped texture as target"); sb::Log::sdl_error("Could not read pixels after setting remapped texture as target");
} }
else else
{ {
@ -226,14 +226,14 @@ void sb::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture*
SDL_FRect draw_rect; SDL_FRect draw_rect;
if (SDL_SetRenderTarget(renderer, texture) < 0) if (SDL_SetRenderTarget(renderer, texture) < 0)
{ {
print_sdl_error("could not set render target"); sb::Log::sdl_error("could not set render target");
} }
else else
{ {
SDL_Rect int_rect = box; SDL_Rect int_rect = box;
if (SDL_RenderSetClipRect(renderer, &int_rect) < 0) if (SDL_RenderSetClipRect(renderer, &int_rect) < 0)
{ {
print_sdl_error("could not set clip"); sb::Log::sdl_error("could not set clip");
} }
else else
{ {
@ -260,7 +260,7 @@ SDL_Texture* sb::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, cons
SDL_Texture* texture; SDL_Texture* texture;
if ((texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y)) == nullptr) if ((texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y)) == nullptr)
{ {
print_sdl_error("could not create texture to fill"); sb::Log::sdl_error("could not create texture to fill");
} }
else else
{ {
@ -274,7 +274,7 @@ SDL_Texture* sb::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, SDL_
SDL_Texture* texture; SDL_Texture* texture;
if ((texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y)) == nullptr) if ((texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y)) == nullptr)
{ {
print_sdl_error("could not create texture to fill"); sb::Log::sdl_error("could not create texture to fill");
} }
else else
{ {
@ -290,7 +290,7 @@ SDL_Texture* sb::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* ba
int w, h; int w, h;
if (SDL_QueryTexture(hue_shifted_texture, &pixel_format, nullptr, &w, &h) < 0) if (SDL_QueryTexture(hue_shifted_texture, &pixel_format, nullptr, &w, &h) < 0)
{ {
print_sdl_error("could not query texture"); sb::Log::sdl_error("could not query texture");
} }
else else
{ {
@ -303,7 +303,7 @@ SDL_Texture* sb::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* ba
Uint32* pixels = new Uint32[length]; Uint32* pixels = new Uint32[length];
if (SDL_RenderReadPixels(renderer, NULL, pixel_format, pixels, bytes_per_row) < 0) if (SDL_RenderReadPixels(renderer, NULL, pixel_format, pixels, bytes_per_row) < 0)
{ {
print_sdl_error("Could not read pixels"); sb::Log::sdl_error("Could not read pixels");
} }
else else
{ {
@ -317,7 +317,7 @@ SDL_Texture* sb::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* ba
} }
if (SDL_UpdateTexture(hue_shifted_texture, NULL, pixels, bytes_per_row) < 0) if (SDL_UpdateTexture(hue_shifted_texture, NULL, pixels, bytes_per_row) < 0)
{ {
print_sdl_error("Could not apply hue shifted pixels update to texture"); sb::Log::sdl_error("Could not apply hue shifted pixels update to texture");
} }
} }
delete[] pixels; delete[] pixels;
@ -341,19 +341,19 @@ SDL_Texture* sb::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, co
SDL_Texture* duplicate = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); SDL_Texture* duplicate = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y);
if (duplicate == NULL) if (duplicate == NULL)
{ {
print_sdl_error("could not create texture from base"); sb::Log::sdl_error("could not create texture from base");
return NULL; return NULL;
} }
if ((SDL_SetRenderTarget(renderer, duplicate)) < 0) if ((SDL_SetRenderTarget(renderer, duplicate)) < 0)
{ {
print_sdl_error("could not set render target to duplicate"); sb::Log::sdl_error("could not set render target to duplicate");
return NULL; return NULL;
} }
SDL_SetTextureBlendMode(base, SDL_BLENDMODE_NONE); SDL_SetTextureBlendMode(base, SDL_BLENDMODE_NONE);
SDL_SetTextureBlendMode(duplicate, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(duplicate, SDL_BLENDMODE_BLEND);
if ((SDL_RenderCopyF(renderer, base, nullptr, nullptr)) < 0) if ((SDL_RenderCopyF(renderer, base, nullptr, nullptr)) < 0)
{ {
print_sdl_error("could not render base onto duplicate"); sb::Log::sdl_error("could not render base onto duplicate");
return nullptr; return nullptr;
} }
SDL_SetTextureBlendMode(base, original_blend_mode); SDL_SetTextureBlendMode(base, original_blend_mode);
@ -367,12 +367,12 @@ SDL_Texture* sb::get_remapped_texture(
SDL_Texture* remapped = duplicate_texture(renderer, base); SDL_Texture* remapped = duplicate_texture(renderer, base);
if (remapped == nullptr) if (remapped == nullptr)
{ {
print_sdl_error("could not duplicate base texture"); sb::Log::sdl_error("could not duplicate base texture");
return nullptr; return nullptr;
} }
if ((SDL_SetRenderTarget(renderer, remapped)) < 0) if ((SDL_SetRenderTarget(renderer, remapped)) < 0)
{ {
print_sdl_error("could not set render target to remapped texture"); sb::Log::sdl_error("could not set render target to remapped texture");
return nullptr; return nullptr;
} }
Pixels pixels = Pixels(renderer, remapped); Pixels pixels = Pixels(renderer, remapped);
@ -399,13 +399,13 @@ SDL_Texture* sb::get_remapped_texture(
SDL_Texture* base = IMG_LoadTexture(renderer, path.c_str()); SDL_Texture* base = IMG_LoadTexture(renderer, path.c_str());
if (base == nullptr) if (base == nullptr)
{ {
print_sdl_error("error loading file"); sb::Log::sdl_error("error loading file");
return nullptr; return nullptr;
} }
SDL_Texture* remapped = get_remapped_texture(renderer, base, map); SDL_Texture* remapped = get_remapped_texture(renderer, base, map);
if (remapped == nullptr) if (remapped == nullptr)
{ {
print_error("could not remap texture"); sb::Log::log("could not remap texture", sb::Log::ERROR);
return nullptr; return nullptr;
} }
SDL_DestroyTexture(base); SDL_DestroyTexture(base);
@ -422,7 +422,7 @@ SDL_Texture* sb::get_pixel_scaled_texture(SDL_Renderer* renderer, SDL_Texture* b
{ {
if ((SDL_SetRenderTarget(renderer, base)) < 0) if ((SDL_SetRenderTarget(renderer, base)) < 0)
{ {
print_sdl_error("could not set render target to remapped texture"); sb::Log::sdl_error("could not set render target to remapped texture");
return nullptr; return nullptr;
} }
glm::ivec2 size = get_texture_box(base).size(); glm::ivec2 size = get_texture_box(base).size();
@ -440,7 +440,7 @@ SDL_Texture* sb::get_pixel_scaled_texture(SDL_Renderer* renderer, SDL_Texture* b
src_begin = src; src_begin = src;
if ((SDL_RenderReadPixels(renderer, NULL, format, src, bytes_per_row)) < 0) if ((SDL_RenderReadPixels(renderer, NULL, format, src, bytes_per_row)) < 0)
{ {
print_sdl_error("could not read pixels after setting remapped texture as target"); sb::Log::sdl_error("could not read pixels after setting remapped texture as target");
return NULL; return NULL;
} }
} }
@ -519,11 +519,11 @@ SDL_Texture* sb::get_pixel_scaled_texture(SDL_Renderer* renderer, SDL_Texture* b
SDL_Texture* scaled = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); SDL_Texture* scaled = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y);
if (scaled == nullptr) if (scaled == nullptr)
{ {
print_sdl_error("could not create scaled texture"); sb::Log::sdl_error("could not create scaled texture");
} }
if (SDL_UpdateTexture(scaled, nullptr, dst_begin, bytes_per_row * 2) < 0) if (SDL_UpdateTexture(scaled, nullptr, dst_begin, bytes_per_row * 2) < 0)
{ {
print_sdl_error("could not copy pixels to scaled texture"); sb::Log::sdl_error("could not copy pixels to scaled texture");
} }
delete[] dst_begin; delete[] dst_begin;
return scaled; return scaled;
@ -557,7 +557,7 @@ SDL_Surface* sb::get_surface_from_pixels(Pixels& pixels)
pixels.format->Amask); pixels.format->Amask);
if (surface == nullptr) if (surface == nullptr)
{ {
print_sdl_error("could not create RGB surface from texture pixel data"); sb::Log::sdl_error("could not create RGB surface from texture pixel data");
} }
else else
{ {
@ -624,16 +624,6 @@ std::string sb::file_to_string(const fs::path& path)
} }
} }
void sb::print_error(const std::string& message)
{
std::cerr << message << std::endl;
}
void sb::print_sdl_error(const std::string& message)
{
std::cerr << message << " " << SDL_GetError() << std::endl;
}
int SDL_SetRenderDrawColor(SDL_Renderer* renderer, const Color& color) int SDL_SetRenderDrawColor(SDL_Renderer* renderer, const Color& color)
{ {
return SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); return SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);

View File

@ -12,7 +12,6 @@
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include <cstdlib> #include <cstdlib>
#include "SDL.h" #include "SDL.h"
#include "SDL_image.h" #include "SDL_image.h"
#include "SDL_pixels.h" #include "SDL_pixels.h"
@ -22,10 +21,10 @@
#include "glm/gtx/vector_angle.hpp" #include "glm/gtx/vector_angle.hpp"
#include "json/json.hpp" #include "json/json.hpp"
#include "sdl2-gfx/SDL2_gfxPrimitives.h" #include "sdl2-gfx/SDL2_gfxPrimitives.h"
#include "Box.hpp" #include "Box.hpp"
#include "Segment.hpp" #include "Segment.hpp"
#include "Color.hpp" #include "Color.hpp"
#include "Log.hpp"
#include "filesystem.hpp" #include "filesystem.hpp"
struct Pixels; struct Pixels;
@ -67,8 +66,6 @@ namespace sb
std::vector<fs::path> glob(fs::path); std::vector<fs::path> 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&); std::string file_to_string(const fs::path&);
void print_error(const std::string&);
void print_sdl_error(const std::string&);
/* Returns an unsorted vector of keys from the passed map */ /* Returns an unsorted vector of keys from the passed map */
template<typename Key, typename Value, template <typename...> class Map> template<typename Key, typename Value, template <typename...> class Map>