naval_swarm/src/singletons/console.hpp
2025-02-03 21:25:04 +01:00

118 lines
3.4 KiB
C++

#pragma once
#include <chrono>
#include <string>
#include <type_traits>
#include <fmt/chrono.h>
#include <fmt/compile.h>
#include <fmt/core.h>
#include <spdlog/sinks/callback_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <godot_cpp/classes/object.hpp>
#include <godot_cpp/classes/rich_text_label.hpp>
namespace rl
{
template <typename TContext>
class Console : public godot::Object
{
GDCLASS(Console, godot::Object);
public:
Console()
{
m_static_inst = this;
init_loggers();
}
~Console()
{
m_static_inst = nullptr;
}
static inline rl::Console<TContext>* get()
{
return m_static_inst;
}
void set_context(TContext* context)
{
m_gui_console = context;
}
void clear_context()
{
m_gui_console = nullptr;
}
void stop_logging()
{
m_logger->flush();
m_stop = true;
}
void init_loggers()
requires std::same_as<TContext, godot::RichTextLabel>
{
auto stdout_sink{ std::make_shared<spdlog::sinks::stdout_color_sink_mt>() };
auto stderr_sink{ std::make_shared<spdlog::sinks::stderr_color_sink_mt>() };
auto callbk_sink{ std::make_shared<spdlog::sinks::callback_sink_mt>(
[this](const spdlog::details::log_msg& msg) {
if (!m_stop.load(std::memory_order_relaxed))
{
if (m_gui_console == nullptr)
return;
using duration_t = std::chrono::duration<double>;
const duration_t elapsed{ clock_t::now() - m_start_time };
m_gui_console->append_text(
fmt::format("[color=gray]{:5} [{:>7.2}] [b]=>[/b] {}[/color]\n",
m_line_num.fetch_add(1, std::memory_order_relaxed), elapsed,
msg.payload)
.c_str());
}
}) };
stderr_sink->set_level(spdlog::level::err);
stdout_sink->set_level(spdlog::level::info);
callbk_sink->set_level(spdlog::level::debug);
m_logger = std::unique_ptr<spdlog::logger>(
new spdlog::logger{ "custom_callback_logger",
{ stdout_sink, stderr_sink, callbk_sink } });
using namespace std::chrono_literals;
spdlog::flush_every(0.25s);
}
template <typename... TArgs>
void print(fmt::format_string<TArgs...> format_str, TArgs&&... args)
{
m_logger->info(format_str, std::forward<TArgs>(args)...);
}
protected:
static void _bind_methods()
{
}
private:
std::unique_ptr<spdlog::logger> m_logger{ nullptr };
std::atomic<bool> m_stop{ false };
std::atomic<uint32_t> m_line_num{ 0 };
TContext* m_gui_console{ nullptr };
using clock_t = std::chrono::high_resolution_clock;
const clock_t::time_point m_start_time{ clock_t::now() };
private:
static inline Console<TContext>* m_static_inst{ nullptr };
};
using console = Console<godot::RichTextLabel>;
}