custom log function; change Game and Node from struct to class
This commit is contained in:
parent
4ece64442f
commit
fff9e13562
|
@ -46,7 +46,7 @@ struct Mushroom : Sprite
|
||||||
|
|
||||||
Mushroom(Node*);
|
Mushroom(Node*);
|
||||||
void update();
|
void update();
|
||||||
std::string get_class_name() { return "Mushroom"; }
|
virtual std::string get_class_name() const { return "Mushroom"; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,6 +71,6 @@ struct Demo : Game
|
||||||
void load_gl_context();
|
void load_gl_context();
|
||||||
void respond(SDL_Event&);
|
void respond(SDL_Event&);
|
||||||
void update();
|
void update();
|
||||||
std::string get_class_name() { return "Demo"; }
|
virtual std::string get_class_name() const { return "Demo"; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
typedef std::function<void()> callback;
|
typedef std::function<void()> callback;
|
||||||
|
|
||||||
struct Node;
|
class Node;
|
||||||
|
|
||||||
struct Animation
|
struct Animation
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct Box : SDL_FRect
|
||||||
bool collide(const Segment&, glm::vec2&) const;
|
bool collide(const Segment&, glm::vec2&) const;
|
||||||
bool collide(const Box&, Box* = nullptr) const;
|
bool collide(const Box&, Box* = nullptr) const;
|
||||||
bool collide(const Box&, Box&) const;
|
bool collide(const Box&, Box&) const;
|
||||||
std::string get_class_name() { return "Box"; }
|
virtual std::string get_class_name() const { return "Box"; }
|
||||||
std::ostream& to_string (std::ostream&) const;
|
std::ostream& to_string (std::ostream&) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,9 +75,10 @@ void Configuration::set_defaults()
|
||||||
sys_config["animation"] = {
|
sys_config["animation"] = {
|
||||||
{"all-frames-frameset-name", "all"}
|
{"all-frames-frameset-name", "all"}
|
||||||
};
|
};
|
||||||
sys_config["logging"] = {
|
sys_config["log"] = {
|
||||||
{"enabled", false},
|
{"enabled", false},
|
||||||
{"debug", false},
|
{"debug-to-stdout", false},
|
||||||
|
{"debug-to-file", false},
|
||||||
{"ouput-directory", "."},
|
{"ouput-directory", "."},
|
||||||
{"info-file-name", "log.txt"},
|
{"info-file-name", "log.txt"},
|
||||||
{"debug-file-name", "debug_log.txt"}
|
{"debug-file-name", "debug_log.txt"}
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct Configuration : Node
|
||||||
void merge();
|
void merge();
|
||||||
void write();
|
void write();
|
||||||
void write(fs::path path);
|
void write(fs::path path);
|
||||||
std::string get_class_name() { return "Configuration"; }
|
virtual std::string get_class_name() const { return "Configuration"; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
106
src/Game.cpp
106
src/Game.cpp
|
@ -39,49 +39,26 @@ void FramerateIndicator::refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(void* userdata, int category, SDL_LogPriority priority, const char* message)
|
|
||||||
{
|
|
||||||
Game* game = static_cast<Game*>(userdata);
|
|
||||||
std::ostream& out = (priority > SDL_LOG_PRIORITY_DEBUG) ? std::cerr : std::cout;
|
|
||||||
out << message << std::endl;
|
|
||||||
if (game->get_configuration()["logging"]["enabled"])
|
|
||||||
{
|
|
||||||
fs::path path = game->get_configuration()["logging"]["output-directory"];
|
|
||||||
if (!fs::exists(path))
|
|
||||||
{
|
|
||||||
fs::create_directories(path);
|
|
||||||
}
|
|
||||||
std::time_t now = std::time(nullptr);
|
|
||||||
std::stringstream stamped_message;
|
|
||||||
stamped_message << std::put_time(std::localtime(&now), "%F %T ") << message;
|
|
||||||
if (game->get_configuration()["logging"]["debug"])
|
|
||||||
{
|
|
||||||
fs::path debug_path = path / game->get_configuration()["logging"]["debug-file-name"];
|
|
||||||
std::ofstream debug_stream(debug_path, std::ios_base::app);
|
|
||||||
debug_stream << stamped_message.str() << std::endl;
|
|
||||||
}
|
|
||||||
if (priority > SDL_LOG_PRIORITY_DEBUG)
|
|
||||||
{
|
|
||||||
fs::path info_path = path / game->get_configuration()["logging"]["info-file-name"];
|
|
||||||
std::ofstream info_stream(info_path, std::ios_base::app);
|
|
||||||
info_stream << stamped_message.str() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::Game()
|
Game::Game()
|
||||||
{
|
{
|
||||||
// use config to determine if debug statements should be printed
|
// set the appropriate priority level for the default log category so either info level messages
|
||||||
if (get_configuration()["logging"]["debug"])
|
// and higher are enabled or debug level messages are enabled, depending on the global configuration
|
||||||
|
SDL_LogPriority default_log_category_priority;
|
||||||
|
if (get_configuration()["log"]["debug-to-file"] || get_configuration()["log"]["debug-to-stdout"])
|
||||||
{
|
{
|
||||||
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
default_log_category_priority = SDL_LOG_PRIORITY_DEBUG;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
default_log_category_priority = SDL_LOG_PRIORITY_INFO;
|
||||||
|
}
|
||||||
|
SDL_LogSetPriority(DEFAULT_SDL_LOG_CATEGORY, default_log_category_priority);
|
||||||
// set custom log function (prints to stdout/stderr and to file if enabled)
|
// set custom log function (prints to stdout/stderr and to file if enabled)
|
||||||
SDL_LogSetOutputFunction(&log, this);
|
SDL_LogSetOutputFunction(&Game::sdl_log_override, this);
|
||||||
// pretty print config to debug log
|
// pretty print config to debug log
|
||||||
std::stringstream config_formatted;
|
std::stringstream config_formatted;
|
||||||
config_formatted << std::setw(4) << get_configuration() << std::endl;
|
config_formatted << std::setw(4) << get_configuration() << std::endl;
|
||||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s", config_formatted.str().c_str());
|
SDL_LogDebug(DEFAULT_SDL_LOG_CATEGORY, "%s", config_formatted.str().c_str());
|
||||||
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());
|
||||||
frame_length_history.reserve(5000);
|
frame_length_history.reserve(5000);
|
||||||
set_framerate(get_configuration()["display"]["framerate"]);
|
set_framerate(get_configuration()["display"]["framerate"]);
|
||||||
|
@ -192,6 +169,48 @@ Game::~Game()
|
||||||
get_delegate().unsubscribe(this);
|
get_delegate().unsubscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 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
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Game::print_error(const std::string& message)
|
void Game::print_error(const std::string& message)
|
||||||
{
|
{
|
||||||
sfw::print_error(message);
|
sfw::print_error(message);
|
||||||
|
@ -288,6 +307,23 @@ void Game::load_gl_context()
|
||||||
log_display_mode();
|
log_display_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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) const
|
||||||
|
{
|
||||||
|
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) const
|
||||||
|
{
|
||||||
|
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, "
|
SDL_Log("renderer name: %s, flags: %i, texture formats: %i, "
|
||||||
|
|
15
src/Game.hpp
15
src/Game.hpp
|
@ -42,16 +42,21 @@ struct FramerateIndicator : Sprite
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void log(void*, int, SDL_LogPriority, const char*);
|
class Game : public Node
|
||||||
|
|
||||||
struct Game : Node
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void sdl_log_override(void*, int, SDL_LogPriority, const char*);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
Game(const Game&) = delete;
|
Game(const Game&) = delete;
|
||||||
Game& operator=(const Game&) = delete;
|
Game& operator=(const Game&) = delete;
|
||||||
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 = NULL;
|
SDL_Renderer* renderer = NULL;
|
||||||
SDL_GLContext glcontext = NULL;
|
SDL_GLContext glcontext = NULL;
|
||||||
|
@ -78,6 +83,8 @@ struct Game : Node
|
||||||
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();
|
||||||
|
void log(const std::string&, const int = DEFAULT_SDL_LOG_CATEGORY) const;
|
||||||
|
void debug(const std::string&, const int = DEFAULT_SDL_LOG_CATEGORY) const;
|
||||||
void log_renderer_info(SDL_RendererInfo&);
|
void log_renderer_info(SDL_RendererInfo&);
|
||||||
bool log_gl_errors(std::string);
|
bool log_gl_errors(std::string);
|
||||||
void log_display_mode();
|
void log_display_mode();
|
||||||
|
@ -98,7 +105,7 @@ struct Game : Node
|
||||||
void set_framerate(int);
|
void set_framerate(int);
|
||||||
void handle_quit_event(SDL_Event&);
|
void handle_quit_event(SDL_Event&);
|
||||||
void quit();
|
void quit();
|
||||||
std::string get_class_name() { return "Game"; }
|
virtual std::string get_class_name() const { return "Game"; }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
float weight(T amount)
|
float weight(T amount)
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct Input : Node
|
||||||
void suppress();
|
void suppress();
|
||||||
void unsuppress();
|
void unsuppress();
|
||||||
bool is_suppressed();
|
bool is_suppressed();
|
||||||
std::string get_class_name() { return "Input"; }
|
virtual std::string get_class_name() const { return "Input"; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
35
src/Node.cpp
35
src/Node.cpp
|
@ -11,8 +11,7 @@ Node::Node() : Node(nullptr) {}
|
||||||
|
|
||||||
Node::Node(Node* parent) : parent(parent)
|
Node::Node(Node* parent) : parent(parent)
|
||||||
{
|
{
|
||||||
std::cout << "Constructing ";
|
debug("constructing node " + get_branch_as_string());
|
||||||
print_branch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::set_parent(Node* other)
|
void Node::set_parent(Node* other)
|
||||||
|
@ -35,6 +34,11 @@ bool Node::is_active() const
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nlohmann::json& Node::get_configuration() const
|
||||||
|
{
|
||||||
|
return get_root()->configuration.config;
|
||||||
|
}
|
||||||
|
|
||||||
nlohmann::json& Node::get_configuration()
|
nlohmann::json& Node::get_configuration()
|
||||||
{
|
{
|
||||||
return get_root()->configuration.config;
|
return get_root()->configuration.config;
|
||||||
|
@ -120,27 +124,34 @@ void Node::unsuppress_input()
|
||||||
get_root()->get_input().unsuppress();
|
get_root()->get_input().unsuppress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::print_branch()
|
void Node::log(const std::string& message) const
|
||||||
{
|
{
|
||||||
Node* current = this;
|
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;
|
||||||
|
std::stringstream branch;
|
||||||
while (current != nullptr)
|
while (current != nullptr)
|
||||||
{
|
{
|
||||||
std::cout << current->get_class_name() << " @ " << current;
|
branch << current->get_class_name() << " @ " << current;
|
||||||
if (current->parent != nullptr)
|
if (current->parent != nullptr)
|
||||||
{
|
{
|
||||||
std::cout << " -> ";
|
branch << " -> ";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
current = current->parent;
|
current = current->parent;
|
||||||
}
|
}
|
||||||
|
return branch.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::~Node()
|
Node::~Node()
|
||||||
{
|
{
|
||||||
// std::cout << "Destructing ";
|
debug("destroying node " + get_branch_as_string());
|
||||||
// print_branch();
|
|
||||||
get_delegate().unsubscribe(this);
|
get_delegate().unsubscribe(this);
|
||||||
}
|
}
|
||||||
|
|
13
src/Node.hpp
13
src/Node.hpp
|
@ -10,16 +10,18 @@
|
||||||
|
|
||||||
#include "filesystem.hpp"
|
#include "filesystem.hpp"
|
||||||
|
|
||||||
struct Game;
|
class Game;
|
||||||
struct Delegate;
|
struct Delegate;
|
||||||
struct Display;
|
struct Display;
|
||||||
struct Input;
|
struct Input;
|
||||||
struct Box;
|
struct Box;
|
||||||
struct Audio;
|
struct Audio;
|
||||||
|
|
||||||
struct Node
|
class Node
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
Node *parent;
|
Node *parent;
|
||||||
SDL_Texture* canvas = nullptr;
|
SDL_Texture* canvas = nullptr;
|
||||||
bool active = true;
|
bool active = true;
|
||||||
|
@ -33,6 +35,7 @@ struct Node
|
||||||
void set_canvas(SDL_Texture*);
|
void set_canvas(SDL_Texture*);
|
||||||
SDL_Texture* get_canvas();
|
SDL_Texture* get_canvas();
|
||||||
bool is_active() const;
|
bool is_active() const;
|
||||||
|
const nlohmann::json& get_configuration() const;
|
||||||
nlohmann::json& get_configuration();
|
nlohmann::json& get_configuration();
|
||||||
Delegate& get_delegate();
|
Delegate& get_delegate();
|
||||||
const Display& get_display() const;
|
const Display& get_display() const;
|
||||||
|
@ -48,8 +51,10 @@ struct Node
|
||||||
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 print_branch();
|
void log(const std::string&) const;
|
||||||
virtual std::string get_class_name() { return "Node"; };
|
void debug(const std::string&) const;
|
||||||
|
const std::string get_branch_as_string() const;
|
||||||
|
virtual std::string get_class_name() const { return "Node"; };
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
|
|
||||||
template<typename T = Game>
|
template<typename T = Game>
|
||||||
|
|
|
@ -62,7 +62,7 @@ struct Recorder : Node
|
||||||
void write_mp4();
|
void write_mp4();
|
||||||
void write_audio(Uint8*, int);
|
void write_audio(Uint8*, int);
|
||||||
void update();
|
void update();
|
||||||
std::string get_class_name() { return "Recorder"; }
|
virtual std::string get_class_name() const { return "Recorder"; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "Animation.hpp"
|
#include "Animation.hpp"
|
||||||
#include "Color.hpp"
|
#include "Color.hpp"
|
||||||
|
|
||||||
struct Game;
|
class Game;
|
||||||
struct Frameset;
|
struct Frameset;
|
||||||
|
|
||||||
struct Sprite : Node
|
struct Sprite : Node
|
||||||
|
@ -143,7 +143,7 @@ struct Sprite : Node
|
||||||
void render_subsection(SDL_Renderer*, SDL_Texture*, const Box&, const Box&);
|
void render_subsection(SDL_Renderer*, SDL_Texture*, const Box&, const Box&);
|
||||||
void set_to_leave_memory_allocated();
|
void set_to_leave_memory_allocated();
|
||||||
void set_to_deallocate_memory();
|
void set_to_deallocate_memory();
|
||||||
virtual std::string get_class_name() { return "Sprite"; }
|
virtual std::string get_class_name() const { return "Sprite"; }
|
||||||
~Sprite() { unload(); }
|
~Sprite() { unload(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue