-
Notifications
You must be signed in to change notification settings - Fork 13
/
console.hpp
117 lines (95 loc) · 3.37 KB
/
console.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#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>;
}