Big code changes
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class Application {
|
||||
public:
|
||||
struct Config {
|
||||
int width;
|
||||
int height;
|
||||
std::string name;
|
||||
bool headless = false;
|
||||
};
|
||||
|
||||
Application(const Application&) = delete;
|
||||
Application& operator=(const Application&) = delete;
|
||||
|
||||
Application(const Config& config);
|
||||
~Application();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <any>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <sophia/types.hpp>
|
||||
#include <sophia/util/delegate.hpp>
|
||||
#include <sophia/util/logger.hpp>
|
||||
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
namespace sophia {
|
||||
// https://github.com/TheCherno/Hazel/blob/1feb70572fa87fa1c4ba784a2cfeada5b4a500db/Hazel/src/Hazel/Events/Event.h
|
||||
|
||||
enum EventCategoryFlags : u32 {
|
||||
None = 0,
|
||||
EventCategoryApplication = BIT(0),
|
||||
EventCategoryInput = BIT(1),
|
||||
EventCategoryKeyboard = BIT(2),
|
||||
EventCategoryMouse = BIT(3),
|
||||
EventCategoryMouseButton = BIT(4)
|
||||
};
|
||||
|
||||
class Event {
|
||||
public:
|
||||
virtual ~Event() = default;
|
||||
|
||||
virtual const char* getName() const = 0;
|
||||
virtual std::string toString() const { return getName(); }
|
||||
|
||||
virtual int getCategoryFlags() const { return EventCategoryFlags::None; };
|
||||
|
||||
inline bool isInCategory(EventCategoryFlags category) {
|
||||
return getCategoryFlags() & category;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DerivedEvent>
|
||||
class EventDelegate : public Delegate<DerivedEvent&> {
|
||||
public:
|
||||
EventDelegate() {
|
||||
static_assert(std::is_base_of<Event, DerivedEvent>::value,
|
||||
"DerivedEvent must derive from Event");
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Event& e) {
|
||||
return os << e.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton class for managing event subscription and dispatching.
|
||||
*
|
||||
* TODO heavy documentation is needed
|
||||
*
|
||||
* @todo impl removing functors from delegate
|
||||
* @warning this class is in heavy development, use at your own risk
|
||||
* @warning NOT THREAD SAFE
|
||||
*/
|
||||
class EventSystem {
|
||||
public:
|
||||
using EventType = decltype(std::declval<std::type_info>().hash_code());
|
||||
|
||||
#define GET_EVENT_TYPE(E) typeid(E).hash_code()
|
||||
|
||||
EventSystem(const EventSystem&) = delete;
|
||||
EventSystem& operator=(const EventSystem&) = delete;
|
||||
|
||||
static EventSystem& get() {
|
||||
static EventSystem instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void addListener(std::function<void(E&)> f) {
|
||||
static_assert(std::is_base_of<Event, E>::value, "E must derive from Event");
|
||||
|
||||
EventType eventType = GET_EVENT_TYPE(E);
|
||||
|
||||
// Ensures pointer to EventDelegate<E> is not null in unordered map
|
||||
if (!this->eventDelegates.count(eventType)) {
|
||||
this->eventDelegates[eventType] =
|
||||
std::make_unique<std::any>(EventDelegate<E>());
|
||||
|
||||
log::trace("EventSystem creating new event type: ", eventType);
|
||||
}
|
||||
|
||||
EventDelegate<E>& delegate =
|
||||
std::any_cast<EventDelegate<E>&>(*eventDelegates[eventType]);
|
||||
delegate.add(f);
|
||||
}
|
||||
|
||||
template <class E, class O>
|
||||
void addMethodListener(void (O::*memberFn)(E&), std::shared_ptr<O> obj) {
|
||||
static_assert(std::is_base_of<Event, E>::value, "E must derive from Event");
|
||||
|
||||
EventType eventType = GET_EVENT_TYPE(E);
|
||||
|
||||
// Ensures pointer to EventDelegate<E> is not null in unordered map
|
||||
if (!this->eventDelegates.count(eventType)) {
|
||||
this->eventDelegates[eventType] =
|
||||
std::make_unique<std::any>(EventDelegate<E>());
|
||||
|
||||
log::trace("EventSystem creating new event type: ", eventType);
|
||||
}
|
||||
|
||||
EventDelegate<E>& delegate =
|
||||
std::any_cast<EventDelegate<E>&>(*eventDelegates[eventType]);
|
||||
delegate.addMethod(memberFn, obj);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void dispatch(E& event) {
|
||||
static_assert(std::is_base_of<Event, E>::value, "E must derive from Event");
|
||||
EventType eventType = GET_EVENT_TYPE(E);
|
||||
|
||||
if (!this->eventDelegates.count(eventType)) { return; }
|
||||
|
||||
try {
|
||||
EventDelegate<E>& delegate =
|
||||
std::any_cast<EventDelegate<E>&>(*this->eventDelegates.at(eventType));
|
||||
delegate.invoke(event);
|
||||
} catch (const std::out_of_range& error) {
|
||||
log::error("event dispatch failed: ", event.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventSystem() { log::info("EventSystem Initialized: ", this); }
|
||||
~EventSystem() { log::info("EventSystem Destroyed"); }
|
||||
|
||||
std::unordered_map<EventType, std::unique_ptr<std::any>> eventDelegates;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <sophia/types.hpp>
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
struct FrameInfo {
|
||||
u32 frameIndex;
|
||||
double elapsedTime;
|
||||
double deltaTime;
|
||||
glm::vec2 currentFramebufferExtent;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <sophia/types.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
using KeyCode = u32;
|
||||
|
||||
namespace Key {
|
||||
|
||||
enum : KeyCode {
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE, /* ' */
|
||||
Comma = GLFW_KEY_COMMA, /* , */
|
||||
Minus = GLFW_KEY_MINUS, /* - */
|
||||
Period = GLFW_KEY_PERIOD, /* . */
|
||||
Slash = GLFW_KEY_SLASH, /* / */
|
||||
D0 = GLFW_KEY_0,
|
||||
D1 = GLFW_KEY_1,
|
||||
D2 = GLFW_KEY_2,
|
||||
D3 = GLFW_KEY_3,
|
||||
D4 = GLFW_KEY_4,
|
||||
D5 = GLFW_KEY_5,
|
||||
D6 = GLFW_KEY_6,
|
||||
D7 = GLFW_KEY_7,
|
||||
D8 = GLFW_KEY_8,
|
||||
D9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON, /* ; */
|
||||
Equal = GLFW_KEY_EQUAL, /* = */
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET, /* [ */
|
||||
Backslash = GLFW_KEY_BACKSLASH, /* \ */
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET, /* ] */
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT, /* ` */
|
||||
World1 = GLFW_KEY_WORLD_1, /* non-US #1 */
|
||||
World2 = GLFW_KEY_WORLD_2, /* non-US #2 */
|
||||
|
||||
/* Function keys */
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KP0 = GLFW_KEY_KP_0,
|
||||
KP1 = GLFW_KEY_KP_1,
|
||||
KP2 = GLFW_KEY_KP_2,
|
||||
KP3 = GLFW_KEY_KP_3,
|
||||
KP4 = GLFW_KEY_KP_4,
|
||||
KP5 = GLFW_KEY_KP_5,
|
||||
KP6 = GLFW_KEY_KP_6,
|
||||
KP7 = GLFW_KEY_KP_7,
|
||||
KP8 = GLFW_KEY_KP_8,
|
||||
KP9 = GLFW_KEY_KP_9,
|
||||
KPDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KPDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KPMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KPSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KPAdd = GLFW_KEY_KP_ADD,
|
||||
KPEnter = GLFW_KEY_KP_ENTER,
|
||||
KPEqual = GLFW_KEY_KP_EQUAL,
|
||||
LeftShift = GLFW_KEY_LEFT_SHIFT,
|
||||
LeftControl = GLFW_KEY_LEFT_CONTROL,
|
||||
LeftAlt = GLFW_KEY_LEFT_ALT,
|
||||
LeftSuper = GLFW_KEY_LEFT_SUPER,
|
||||
RightShift = GLFW_KEY_RIGHT_SHIFT,
|
||||
RightControl = GLFW_KEY_RIGHT_CONTROL,
|
||||
RightAlt = GLFW_KEY_RIGHT_ALT,
|
||||
RightSuper = GLFW_KEY_RIGHT_SUPER,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
|
||||
} // namespace Key
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <sophia/event.hpp>
|
||||
#include <sophia/key_codes.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class KeyEvent : public Event {
|
||||
public:
|
||||
KeyCode getKeyCode() const { return this->keycode; }
|
||||
|
||||
virtual int getCategoryFlags() const override {
|
||||
return EventCategoryKeyboard | EventCategoryInput;
|
||||
}
|
||||
|
||||
protected:
|
||||
KeyEvent(const KeyCode keycode) : keycode{keycode} {}
|
||||
|
||||
KeyCode keycode;
|
||||
};
|
||||
|
||||
class KeyPressedEvent : public KeyEvent {
|
||||
public:
|
||||
KeyPressedEvent(const KeyCode keycode, bool repeated = false)
|
||||
: KeyEvent{keycode}, repeated{repeated} {}
|
||||
|
||||
bool isRepeat() const { return this->repeated; }
|
||||
|
||||
std::string toString() const override {
|
||||
std::stringstream ss;
|
||||
ss << "KeyPressedEvent: " << this->keycode
|
||||
<< " (repeat = " << this->repeated << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual const char* getName() const override { return "KeyPressed"; }
|
||||
|
||||
private:
|
||||
bool repeated;
|
||||
};
|
||||
|
||||
class KeyReleasedEvent : public KeyEvent {
|
||||
public:
|
||||
KeyReleasedEvent(const KeyCode keycode) : KeyEvent{keycode} {}
|
||||
|
||||
std::string toString() const override {
|
||||
std::stringstream ss;
|
||||
ss << "KeyReleasedEvent: " << this->keycode;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual const char* getName() const override { return "KeyReleased"; }
|
||||
};
|
||||
|
||||
class KeyTypedEvent : public KeyEvent {
|
||||
public:
|
||||
KeyTypedEvent(const KeyCode keycode) : KeyEvent{keycode} {}
|
||||
|
||||
std::string toString() const override {
|
||||
std::stringstream ss;
|
||||
ss << "KeyTypedEvent: " << this->keycode;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual const char* getName() const override { return "KeyTyped"; }
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
using u8 = uint8_t;
|
||||
using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
using u64 = uint64_t;
|
||||
|
||||
using s8 = int8_t;
|
||||
using s16 = int16_t;
|
||||
using s32 = int32_t;
|
||||
using s64 = int64_t;
|
||||
|
||||
using f32 = float;
|
||||
using f64 = double;
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include <sophia/util/logger.hpp>
|
||||
|
||||
#define DEFAULT_DELEGATE_FUNCTOR_ALLOC 5
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class expired_weak_object : public std::runtime_error {
|
||||
public:
|
||||
explicit expired_weak_object(const std::string& message)
|
||||
: std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a weak function that safely calls a method if the
|
||||
* object is alive.
|
||||
*
|
||||
* @tparam O Class owning the method
|
||||
* @tparam A Variadic template parameters for the method arguments
|
||||
*
|
||||
* @param method Pointer to the static method to be called
|
||||
* @param obj Shared pointer to the object instance
|
||||
* @returns std::function that calls method on obj if alive, or throws if
|
||||
* expired
|
||||
* @throws std::invalid_argument If obj is null.
|
||||
* @throws expired_weak_object If the object has expired when called
|
||||
*
|
||||
* @note Could investigate removing throwing exceptions, and instead return a
|
||||
* bool if the weak pointer is alive. This may improve performance
|
||||
*/
|
||||
template <class O, typename... A>
|
||||
std::function<void(A...)> createWeakFunction(void (O::*method)(A...),
|
||||
std::shared_ptr<O> obj) {
|
||||
if (!obj) { throw std::invalid_argument("method and obj must not be null"); }
|
||||
|
||||
std::weak_ptr<O> weakObj = obj;
|
||||
|
||||
return std::function<void(A...)>([method = std::move(method),
|
||||
weakObj = std::move(weakObj)](A... args) {
|
||||
if (auto lockedObj = weakObj.lock()) {
|
||||
(lockedObj.get()->*method)(std::forward<A>(args)...);
|
||||
} else {
|
||||
throw expired_weak_object("Attempting to call function of a dead class");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename... A>
|
||||
class Delegate {
|
||||
public:
|
||||
using Functor = std::function<void(A...)>;
|
||||
|
||||
Delegate() { this->functors.reserve(DEFAULT_DELEGATE_FUNCTOR_ALLOC); }
|
||||
|
||||
void add(const Functor& func) { functors.push_back(func); }
|
||||
|
||||
template <class O>
|
||||
void addMethod(void (O::*memberFn)(A...), std::shared_ptr<O> obj) {
|
||||
functors.push_back(createWeakFunction(memberFn, obj));
|
||||
}
|
||||
|
||||
void clear() { this->functors.clear(); }
|
||||
|
||||
void invoke(A... args) {
|
||||
if (this->functors.empty()) {
|
||||
log::warning("invoking empty delegate");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<size_t> deadFunctorIndexs;
|
||||
|
||||
for (size_t i = 0; i < functors.size(); i++) {
|
||||
if (this->functors[i]) {
|
||||
try {
|
||||
this->functors[i](std::forward<A>(args)...);
|
||||
} catch (const expired_weak_object& e) {
|
||||
log::error("delegate invoke error: ", e.what());
|
||||
deadFunctorIndexs.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = deadFunctorIndexs.rbegin(); it != deadFunctorIndexs.rend();
|
||||
++it) {
|
||||
functors.erase(functors.begin() + *it);
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(Functor c) {
|
||||
clear();
|
||||
|
||||
if (c != nullptr) { add(c); }
|
||||
}
|
||||
|
||||
void operator+=(Functor c) { add(c); }
|
||||
|
||||
void operator()() { invoke(); }
|
||||
|
||||
private:
|
||||
std::vector<Functor> functors;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Lots of work still needs to be done in here.
|
||||
*
|
||||
* Usage:
|
||||
* using namespace sophia;
|
||||
* log::fatal("fatal message")
|
||||
* log::info("Infomation message")
|
||||
*
|
||||
* TODO Impl some form of log error handling
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include <sophia/types.hpp>
|
||||
|
||||
namespace sophia::log {
|
||||
|
||||
enum class LEVEL {
|
||||
NONE,
|
||||
FATAL,
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO,
|
||||
VERBOSE,
|
||||
DEBUGGING,
|
||||
TRACE,
|
||||
};
|
||||
|
||||
// Helper print functions
|
||||
#define LOG_PRINT_HELPER(MSG) std::cout << MSG
|
||||
#define LOG_PREFIX_FATAL LOG_PRINT_HELPER("\033[1;91m[FATAL]\033[0m ")
|
||||
#define LOG_PREFIX_ERROR LOG_PRINT_HELPER("\033[1;31m[ERROR]\033[0m ")
|
||||
#define LOG_PREFIX_WARNING LOG_PRINT_HELPER("\033[1;33m[WARNING]\033[0m ")
|
||||
#define LOG_PREFIX_INFO LOG_PRINT_HELPER("\033[32m[INFO]\033[0m ")
|
||||
#define LOG_PREFIX_VERBOSE LOG_PRINT_HELPER("\033[36m[VERBOSE]\033[0m ")
|
||||
#define LOG_PREFIX_DEBUG LOG_PRINT_HELPER("\033[1;34m[DEBUG]\033[0m ")
|
||||
#define LOG_PREFIX_TRACE LOG_PRINT_HELPER("\033[1;90m[TRACE]\033[0m ")
|
||||
|
||||
template <typename... Args>
|
||||
void log(LEVEL level = LEVEL::NONE, Args... args) {
|
||||
#ifndef NDEBUG
|
||||
switch (level) {
|
||||
case LEVEL::FATAL:
|
||||
LOG_PREFIX_FATAL;
|
||||
break;
|
||||
case LEVEL::ERROR:
|
||||
LOG_PREFIX_ERROR;
|
||||
break;
|
||||
case LEVEL::WARNING:
|
||||
LOG_PREFIX_WARNING;
|
||||
break;
|
||||
case LEVEL::INFO:
|
||||
LOG_PREFIX_INFO;
|
||||
break;
|
||||
case LEVEL::VERBOSE:
|
||||
LOG_PREFIX_VERBOSE;
|
||||
break;
|
||||
// case LEVEL::DEBUGGING:
|
||||
// LOG_PREFIX_DEBUG;
|
||||
// break;
|
||||
case LEVEL::TRACE:
|
||||
LOG_PREFIX_TRACE;
|
||||
break;
|
||||
default:
|
||||
std::cout << "\033[1;90m[LOG]\033[0m ";
|
||||
break;
|
||||
}
|
||||
|
||||
((std::cout << ' ' << std::forward<Args>(args)), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)level;
|
||||
(void)std::initializer_list<int>{((void)args, 0)...};
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void fatal(Args... args) {
|
||||
log(LEVEL::FATAL, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void error(Args... args) {
|
||||
log(LEVEL::ERROR, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void warning(Args... args) {
|
||||
log(LEVEL::WARNING, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void info(Args... args) {
|
||||
log(LEVEL::INFO, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void verbose(Args... args) {
|
||||
log(LEVEL::VERBOSE, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void debug(const char* file, u16 line, Args... args) {
|
||||
#ifndef NDEBUG
|
||||
LOG_PREFIX_DEBUG;
|
||||
std::cout << file << "::" << line;
|
||||
((std::cout << ' ' << std::forward<Args>(args)), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)std::initializer_list<int>{((void)args, 0)...};
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
// trick
|
||||
#define debug(...) debug(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
template <typename... Args>
|
||||
void trace(Args... args) {
|
||||
log(LEVEL::TRACE, args...);
|
||||
}
|
||||
|
||||
} // namespace sophia::log
|
||||
Reference in New Issue
Block a user