diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..079413f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "C_Cpp.default.cppStandard": "c++20", + "cmake.debugConfig": { + "cwd": "${workspaceFolder}" + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 24fd749..ac0c6bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,13 @@ cmake_minimum_required(VERSION 3.31) project(Ugly) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) + find_package(GLEW REQUIRED) find_package(glfw3 CONFIG REQUIRED) find_package(glm CONFIG REQUIRED) add_subdirectory(./source/app) +add_subdirectory(./source/log) add_subdirectory(./source/shader) diff --git a/assets/shaders/shader.frag b/assets/shaders/shader.frag index cca0412..cb20cbc 100644 --- a/assets/shaders/shader.frag +++ b/assets/shaders/shader.frag @@ -5,4 +5,4 @@ out vec4 color; void main() { color = vec4(_color, 1.0); -} \ No newline at end of file +} diff --git a/assets/shaders/shader.vert b/assets/shaders/shader.vert index 66e6211..3301671 100644 --- a/assets/shaders/shader.vert +++ b/assets/shaders/shader.vert @@ -7,4 +7,4 @@ out vec3 _color; void main() { _color = color; gl_Position = vec4(position, 0.0, 1.0); -} \ No newline at end of file +} diff --git a/source/app/CMakeLists.txt b/source/app/CMakeLists.txt index be99367..898aa95 100644 --- a/source/app/CMakeLists.txt +++ b/source/app/CMakeLists.txt @@ -13,5 +13,6 @@ target_link_libraries(${PROJECT_NAME} GLEW::GLEW glfw glm::glm + UglyLogLib UglyShaderLib ) diff --git a/source/app/main.cpp b/source/app/main.cpp index d16406b..aced843 100644 --- a/source/app/main.cpp +++ b/source/app/main.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/source/app/src/App.cpp b/source/app/src/App.cpp index 7e50cfd..31d43b9 100644 --- a/source/app/src/App.cpp +++ b/source/app/src/App.cpp @@ -1,24 +1,31 @@ #include "App.hpp" -#include #include #include #include +#include "LogUtils.hpp" #include "ShaderProgramBuilder.hpp" +#include "TimestampLog.hpp" + int App::main(std::vector &args) { + auto cerrLog = ugly::TimestampLog{std::cerr, "ugly::log"}; + ugly::log = ugly::LogAlias{&cerrLog}; + ugly::log("hello, world! app started."); + auto app = App{}; app.game_loop(); - return EXIT_SUCCESS; + + ugly::log("app quitting."); + return 0; } void App::error_callback_s(int error, const char *description) { - std::cerr << "[GLFW error]: " << description << '\n'; - exit(EXIT_FAILURE); + ugly::log("(glfw error): {}", description); } @@ -45,7 +52,7 @@ App::App(): glfwMakeContextCurrent(mpWindow); glewExperimental = GL_TRUE; if(glewInit() != GLEW_OK) { - error_callback_s(GLFW_NO_ERROR, "glewInit() failed"); + ugly::log("glewInit() failed!"); } float vertices[] = { diff --git a/source/log/CMakeLists.txt b/source/log/CMakeLists.txt new file mode 100644 index 0000000..62f9bc0 --- /dev/null +++ b/source/log/CMakeLists.txt @@ -0,0 +1,11 @@ +project(UglyLogLib) + +add_library(${PROJECT_NAME} + ./src/globals.cpp + ./src/TimestampLog.cpp +) + +target_include_directories(${PROJECT_NAME} + PUBLIC ./include + PRIVATE ./src +) diff --git a/source/log/include/ILogFacility.hpp b/source/log/include/ILogFacility.hpp new file mode 100644 index 0000000..fea9469 --- /dev/null +++ b/source/log/include/ILogFacility.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace ugly { + +class ILogFacility { +public: + virtual void vlog(std::string_view fmt, std::format_args args) = 0; +}; + +} diff --git a/source/log/include/LogUtils.hpp b/source/log/include/LogUtils.hpp new file mode 100644 index 0000000..800824e --- /dev/null +++ b/source/log/include/LogUtils.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "ILogFacility.hpp" + +#include + +namespace ugly { + +class LogAlias { +public: + ILogFacility *mpLog; + + template + LogAlias &operator()(std::format_string format, Args &&...args) { + if(mpLog) { + mpLog->vlog(format.get(), std::make_format_args(args...)); + } + return *this; + } +}; + +extern LogAlias log; + +} diff --git a/source/log/include/TimestampLog.hpp b/source/log/include/TimestampLog.hpp new file mode 100644 index 0000000..aa98d8a --- /dev/null +++ b/source/log/include/TimestampLog.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "ILogFacility.hpp" + +#include +#include +#include +#include +#include + +namespace ugly { + +class TimestampLog: virtual public ILogFacility { +private: + std::ostream &mrOutputStream; + std::string mDescription; + std::chrono::high_resolution_clock::time_point mStart; + +public: + TimestampLog(std::ostream &os, std::string_view description); + void vlog(std::string_view fmt, std::format_args args) override; +}; + +} diff --git a/source/log/src/TimestampLog.cpp b/source/log/src/TimestampLog.cpp new file mode 100644 index 0000000..4e00506 --- /dev/null +++ b/source/log/src/TimestampLog.cpp @@ -0,0 +1,18 @@ +#include "TimestampLog.hpp" + +#include +#include + + +ugly::TimestampLog::TimestampLog(std::ostream &os, std::string_view description): + mrOutputStream{os}, + mDescription{description}, + mStart{std::chrono::high_resolution_clock::now()} {} + + +void ugly::TimestampLog::vlog(std::string_view fmt, std::format_args args) { + auto now = std::chrono::high_resolution_clock::now(); + auto timestamp = std::chrono::duration_cast>(now - mStart).count(); + auto message = std::vformat(fmt, args); + mrOutputStream << std::format("[{:9.4f}] {}: {}\n", timestamp, mDescription, message); +} diff --git a/source/log/src/globals.cpp b/source/log/src/globals.cpp new file mode 100644 index 0000000..637dae2 --- /dev/null +++ b/source/log/src/globals.cpp @@ -0,0 +1,3 @@ +#include "LogUtils.hpp" + +ugly::LogAlias ugly::log{nullptr}; diff --git a/source/shader/CMakeLists.txt b/source/shader/CMakeLists.txt index 8446c1d..e730765 100644 --- a/source/shader/CMakeLists.txt +++ b/source/shader/CMakeLists.txt @@ -11,4 +11,5 @@ target_include_directories(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} GLEW::GLEW + UglyLogLib ) diff --git a/source/shader/include/ShaderProgramBuilder.hpp b/source/shader/include/ShaderProgramBuilder.hpp index 90476fd..98e65e9 100644 --- a/source/shader/include/ShaderProgramBuilder.hpp +++ b/source/shader/include/ShaderProgramBuilder.hpp @@ -7,12 +7,9 @@ namespace ugly{ class ShaderProgramBuilder { -public: - class Error: public std::runtime_error{ - public: - using std::runtime_error::runtime_error; - }; - +private: + GLuint mProgram; + public: ShaderProgramBuilder(); ~ShaderProgramBuilder(); @@ -20,9 +17,6 @@ public: ShaderProgramBuilder &attachFromMemory(GLenum type, const GLchar *string, GLint length = 0); ShaderProgramBuilder &attachFromFile(GLenum type, const char *filename); GLuint link(); - -private: - GLuint mProgram; }; } diff --git a/source/shader/src/ShaderProgramBuilder.cpp b/source/shader/src/ShaderProgramBuilder.cpp index 05e3a27..0fe8117 100644 --- a/source/shader/src/ShaderProgramBuilder.cpp +++ b/source/shader/src/ShaderProgramBuilder.cpp @@ -1,14 +1,14 @@ #include "ShaderProgramBuilder.hpp" #include -#include #include #include +#include "LogUtils.hpp" + ugly::ShaderProgramBuilder::ShaderProgramBuilder(): - mProgram{glCreateProgram()} { -} + mProgram{glCreateProgram()} {} ugly::ShaderProgramBuilder::~ShaderProgramBuilder() { @@ -20,7 +20,8 @@ ugly::ShaderProgramBuilder::~ShaderProgramBuilder() { void ugly::ShaderProgramBuilder::reset() { using namespace std; - swap(*this, ShaderProgramBuilder{}); + ShaderProgramBuilder b; + swap(*this, b); } @@ -35,8 +36,7 @@ ugly::ShaderProgramBuilder &ugly::ShaderProgramBuilder::attachFromMemory(GLenum char buf[512]; glGetShaderInfoLog(shader, 512, NULL, buf); glDeleteShader(shader); - std::cerr << "Failed to compile shader:\n\t" << buf << '\n'; - throw Error{"shader failed to compile"}; + ugly::log("failed to compile shader:\n\t{}", buf); } glAttachShader(mProgram, shader); @@ -48,8 +48,14 @@ ugly::ShaderProgramBuilder &ugly::ShaderProgramBuilder::attachFromMemory(GLenum ugly::ShaderProgramBuilder &ugly::ShaderProgramBuilder::attachFromFile(GLenum type, const char *filename) { auto file = std::filebuf{}; auto ss = std::ostringstream{}; - ss.exceptions(std::ios_base::badbit); - ss << file.open(filename, std::ios_base::in); + + ugly::log("loading shader from file {}", filename); + file.open(filename, std::ios_base::in); + if(!file.is_open()) { + ugly::log("couldn't open file {}", filename); + } + + ss << &file; return attachFromMemory(type, ss.str().c_str()); } @@ -62,8 +68,7 @@ GLuint ugly::ShaderProgramBuilder::link() { if(status != GL_TRUE) { char buf[512]; glGetProgramInfoLog(mProgram, 512, NULL, buf); - std::cerr << "Failed to link program:\n\t" << buf << '\n'; - throw Error{"program failed to link"}; + ugly::log("failed to link program:\n\t{}", buf); } auto result = mProgram;