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;
message << "config file modified, reloading " << config_path;
debug(message.str());
sb::Log::log(message, sb::Log::DEBUG);
load();
}
}

View File

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

View File

@ -1,5 +1,4 @@
#include "Display.hpp"
#include "Game.hpp"
/* Create a Display instance and subscribe to commands */
Display::Display(Node* parent) : Node(parent)
@ -28,7 +27,9 @@ Uint32 Display::pixel_format(int display_index) const
SDL_DisplayMode display_mode;
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;
}
else
@ -123,12 +124,12 @@ void Display::toggle_fullscreen() const
SDL_Window* window = const_cast<SDL_Window*>(get_window());
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN)
{
log("fullscreen requested");
sb::Log::log("fullscreen requested");
SDL_SetWindowFullscreen(window, 0);
}
else
{
log("exit fullscreen requested");
sb::Log::log("exit fullscreen requested");
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
}
}

View File

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

View File

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

View File

@ -1,44 +1,5 @@
#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()
{
/* 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;
}
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 */
SDL_LogSetOutputFunction(&Game::sdl_log_override, this);
/* pretty print config to debug log */
std::ostringstream log_message;
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 */
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 */
@ -77,17 +38,17 @@ Game::Game()
SDL_GetVersion(&version);
log_message << "linked to SDL " << static_cast<int>(version.major) << "." << static_cast<int>(version.minor) << "." <<
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 */
SDL_SetMainReady();
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();
}
log_message = std::ostringstream();
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>();
/* Create a window with dimensions set in the config, centered, and flagged to be usable in OpenGL context */
window = SDL_CreateWindow(
@ -95,7 +56,7 @@ Game::Game()
SDL_WINDOWPOS_CENTERED, window_size.x, window_size.y, SDL_WINDOW_OPENGL);
if (window == nullptr)
{
print_sdl_error("Could not create window");
sb::Log::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
@ -103,7 +64,7 @@ Game::Game()
*/
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();
}
else
@ -113,7 +74,7 @@ Game::Game()
SDL_GetRendererOutputSize(renderer, &w, &h);
log_message = std::ostringstream();
log_message << "renderer output size is " << w << "x" << h;
log(log_message.str());
sb::Log::log(log_message);
/* clear screen to black */
SDL_SetRenderTarget(renderer, nullptr);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
@ -125,7 +86,7 @@ Game::Game()
SDL_ShowCursor(get_configuration()["display"]["show-cursor"]);
if (TTF_Init() < 0)
{
print_sdl_error("Could not initialize SDL ttf");
sb::Log::sdl_error("Could not initialize SDL ttf");
flag_to_end();
}
else
@ -135,11 +96,11 @@ Game::Game()
}
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)
{
print_sdl_error("Could not initialize SDL mixer");
sb::Log::sdl_error("Could not initialize SDL mixer");
flag_to_end();
}
else
@ -151,20 +112,22 @@ Game::Game()
// MIX_DEFAULT_CHANNELS, 1024) < 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());
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));
std::ostringstream message;
message << "Found audio capture device " << ii << ": " << SDL_GetAudioDeviceName(ii, SDL_TRUE);
sb::Log::log(message);
}
audio.load_sfx();
audio.load_bgm();
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
log("big endian");
sb::Log::log("big endian");
#else
log("little endian");
sb::Log::log("little endian");
#endif
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)
{
print_sdl_error("Could not create renderer");
sb::Log::sdl_error("Could not create renderer");
flag_to_end();
}
else
@ -216,46 +179,45 @@ void Game::load_gl_context()
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
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();
}
/* try enabling vsync */
if (SDL_GL_SetSwapInterval(1) == 0)
{
log("enabled vsync");
sb::Log::log("enabled vsync");
}
else
{
log("vsync not supported");
sb::Log::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());
sb::Log::log(message, sb::Log::ERROR);
}
message << "OpenGL " << glGetString(GL_VERSION) << ", renderer " << glGetString(GL_RENDERER) << ", shading language " <<
glGetString(GL_SHADING_LANGUAGE_VERSION);
log(message.str());
sb::Log::log(message);
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
* 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)
{
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
/* 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
/* handle writing to log file */
if (game->get_configuration()["log"]["enabled"])
{
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);
}
// prepend a timestamp to the message
/* 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 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
/* 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"];
@ -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()
{
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)
{
message << "compiled shader at " << path;
log(message.str());
sb::Log::log(message);
return shader;
}
else
@ -330,7 +282,7 @@ GLuint Game::load_shader(const fs::path& path, GLenum type) const
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());
sb::Log::log(message, sb::Log::Level::ERROR);
return -1;
}
}
@ -344,7 +296,7 @@ bool Game::link_shader(GLuint program) const
if (is_linked == GL_TRUE)
{
message << "linked shader program " << program;
log(message.str());
sb::Log::log(message);
return true;
}
else
@ -356,81 +308,18 @@ bool Game::link_shader(GLuint program) const
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());
sb::Log::log(message, sb::Log::Level::ERROR);
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)
{
SDL_Log("renderer name: %s, flags: %i, texture formats: %i, "
"max texture w: %i, max texture h: %i", info.name, info.flags,
info.num_texture_formats, info.max_texture_width,
info.max_texture_height);
}
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;
std::ostringstream message;
message << "renderer name: " << info.name << ", flags: " << info.flags << ", texture formats: " <<
info.num_texture_formats << ", max texture w: " << info.max_texture_width << ", max texture h: " <<
info.max_texture_height;
sb::Log::log(message);
}
/* 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);
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
{
message << "Display #" << ii << ": display mode is " << current.w << "x" << current.h << "px @ " <<
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);
}
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 "Sprite.hpp"
#include "Audio.hpp"
#include "Log.hpp"
#include "filesystem.hpp"
#include "extension.hpp"
@ -71,7 +72,6 @@ public:
Game(Game&&) = delete;
Game& operator=(Game&&) = delete;
static const int DEFAULT_SDL_LOG_CATEGORY = SDL_LOG_CATEGORY_CUSTOM;
SDL_Window* window;
SDL_Renderer* renderer = nullptr;
SDL_GLContext glcontext = nullptr;
@ -90,17 +90,12 @@ public:
Game();
virtual void reset() { activate(); }
void print_error(const std::string&);
void print_sdl_error(const std::string&);
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;
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&);
static 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);

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)
{
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)
@ -124,16 +124,6 @@ void Node::unsuppress_input()
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 Node* current = this;
@ -152,6 +142,6 @@ const std::string Node::get_branch_as_string() const
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);
}

View File

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

View File

@ -11,11 +11,11 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const Box& box) :
SDL_DisplayMode display_mode;
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)
{
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;
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);
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);
}
else
@ -74,12 +74,12 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const Box& box) :
int pitch;
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
{
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 "Box.hpp"
#include "Color.hpp"
#include "Log.hpp"
#include "extension.hpp"
class Sprite;

View File

@ -43,7 +43,7 @@ void Recorder::respond(SDL_Event& event)
}
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"))
@ -52,7 +52,9 @@ void Recorder::respond(SDL_Event& event)
}
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);
std::ostringstream message;
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
@ -87,7 +89,7 @@ void Recorder::grab_stash()
int length = get_configuration()["recording"]["max-stash-length"];
std::ostringstream message;
message << "stashing most recent " << length / 1000.0f << " seconds of video";
log(message.str());
sb::Log::log(message);
most_recent_stash = current_stash;
current_stash = Stash();
writing_recording = true;
@ -97,7 +99,7 @@ void Recorder::grab_stash()
}
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();
}
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;
}
@ -125,7 +129,7 @@ void Recorder::start_recording()
{
if (!writing_recording)
{
log("starting recording");
sb::Log::log("starting recording");
is_recording = true;
video_stashes.push_back(Stash());
make_directory();
@ -133,7 +137,7 @@ void Recorder::start_recording()
}
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 "Node.hpp"
#include "Animation.hpp"
#include "Log.hpp"
struct Stash
{

View File

@ -44,7 +44,7 @@ void Sprite::associate(std::string path)
{
std::ostringstream message;
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);
if (not texture)
{
game->print_sdl_error("Could not load image");
sb::Log::sdl_error("Could not load image");
}
else
{

View File

@ -15,6 +15,7 @@
#include "Box.hpp"
#include "Animation.hpp"
#include "Color.hpp"
#include "Log.hpp"
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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 */
@ -65,7 +65,7 @@ void Texture::load(SDL_Surface* surface)
load(surface->pixels, {surface->w, surface->h}, GL_RGBA, GL_UNSIGNED_BYTE);
std::ostringstream message;
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 */
@ -77,7 +77,7 @@ void Texture::load(void* pixels, glm::vec2 size, GLenum format, GLenum type)
}
bind();
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 */

View File

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

View File

@ -99,7 +99,7 @@ void sb::populate_pixel_2d_array(
int access;
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
{
@ -109,7 +109,7 @@ void sb::populate_pixel_2d_array(
}
if (SDL_SetRenderTarget(renderer, texture) < 0)
{
print_sdl_error("Could not set render target");
sb::Log::sdl_error("Could not set render target");
}
else
{
@ -121,7 +121,7 @@ void sb::populate_pixel_2d_array(
SDL_Rect int_rect = region;
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
{
@ -226,14 +226,14 @@ void sb::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture*
SDL_FRect draw_rect;
if (SDL_SetRenderTarget(renderer, texture) < 0)
{
print_sdl_error("could not set render target");
sb::Log::sdl_error("could not set render target");
}
else
{
SDL_Rect int_rect = box;
if (SDL_RenderSetClipRect(renderer, &int_rect) < 0)
{
print_sdl_error("could not set clip");
sb::Log::sdl_error("could not set clip");
}
else
{
@ -260,7 +260,7 @@ SDL_Texture* sb::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, cons
SDL_Texture* texture;
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
{
@ -274,7 +274,7 @@ SDL_Texture* sb::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, SDL_
SDL_Texture* texture;
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
{
@ -290,7 +290,7 @@ SDL_Texture* sb::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* ba
int w, h;
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
{
@ -303,7 +303,7 @@ SDL_Texture* sb::get_hue_shifted_texture(SDL_Renderer* renderer, SDL_Texture* ba
Uint32* pixels = new Uint32[length];
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
{
@ -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)
{
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;
@ -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);
if (duplicate == NULL)
{
print_sdl_error("could not create texture from base");
sb::Log::sdl_error("could not create texture from base");
return NULL;
}
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;
}
SDL_SetTextureBlendMode(base, SDL_BLENDMODE_NONE);
SDL_SetTextureBlendMode(duplicate, SDL_BLENDMODE_BLEND);
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;
}
SDL_SetTextureBlendMode(base, original_blend_mode);
@ -367,12 +367,12 @@ SDL_Texture* sb::get_remapped_texture(
SDL_Texture* remapped = duplicate_texture(renderer, base);
if (remapped == nullptr)
{
print_sdl_error("could not duplicate base texture");
sb::Log::sdl_error("could not duplicate base texture");
return nullptr;
}
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;
}
Pixels pixels = Pixels(renderer, remapped);
@ -399,13 +399,13 @@ SDL_Texture* sb::get_remapped_texture(
SDL_Texture* base = IMG_LoadTexture(renderer, path.c_str());
if (base == nullptr)
{
print_sdl_error("error loading file");
sb::Log::sdl_error("error loading file");
return nullptr;
}
SDL_Texture* remapped = get_remapped_texture(renderer, base, map);
if (remapped == nullptr)
{
print_error("could not remap texture");
sb::Log::log("could not remap texture", sb::Log::ERROR);
return nullptr;
}
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)
{
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;
}
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;
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;
}
}
@ -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);
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)
{
print_sdl_error("could not copy pixels to scaled texture");
sb::Log::sdl_error("could not copy pixels to scaled texture");
}
delete[] dst_begin;
return scaled;
@ -557,7 +557,7 @@ SDL_Surface* sb::get_surface_from_pixels(Pixels& pixels)
pixels.format->Amask);
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
{
@ -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)
{
return SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);

View File

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