Compare commits

..

14 Commits

Author SHA1 Message Date
NaifBanana
1efe2a0a7c Mild updates to Window and other pieces to match the rest 2026-06-11 04:25:26 -05:00
NaifBanana
ea632614b0 Make VertexAttributePointer store index instead of buffer pointer 2026-06-11 04:25:26 -05:00
NaifBanana
3048d524b7 Made buildable now 2026-06-11 04:25:26 -05:00
NaifBanana
7648a77e1a Large OpenGL Object handling overhaul 2026-06-11 04:25:26 -05:00
NaifBanana
cff7164d27 Mild cleanup 2026-06-11 04:24:06 -05:00
NaifBanana
13ef940b2d Formatting tweaks 2026-06-11 04:24:06 -05:00
NaifBanana
58121bdf28 Got logging and errors basically all working the way I want 2026-06-11 04:24:06 -05:00
NaifBanana
0f62aecfa3 Error logging almost working! 2026-06-11 04:24:06 -05:00
NaifBanana
40cf079e9d Added type traits and string utils 2026-06-11 04:24:06 -05:00
NaifBanana
fb695798e7 nb::Error objects now working 2026-06-11 04:24:06 -05:00
NaifBanana
e1c456bfe4 I mean it compiled 2026-06-11 04:24:06 -05:00
NaifBanana
e23e062e58 Man im so tired This is wrong but I can taste it, im close 2026-06-11 04:24:06 -05:00
NaifBanana
fd7d36e4be Added more Util tests and str-wstr related changes to util functions 2026-06-11 04:24:06 -05:00
NaifBanana
0b473c0f8a Made errors mostly work as hoped 2026-06-11 04:24:06 -05:00
15 changed files with 226 additions and 176 deletions

View File

@ -6,9 +6,11 @@
#include <memory>
#include <string>
#include <type_traits>
#include "TypeTraits.hpp"
#include <unordered_map>
#include "Logger.hpp"
#include "StringUtils.hpp"
#include "TypeTraits.hpp"
namespace nb {
@ -273,8 +275,38 @@ public:
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
} // namespace nb
#ifdef _NB_AUTOLOG
#ifdef _NB_CODE_ERROR_LOCATIONS
#ifndef LOG
#define LOG(args...) nb::logger.log(args, __FILE__, __LINE__)
#endif // LOG
#ifndef WARN
#define WARN(args...) nb::logger.warn(args, __FILE__, __LINE__)
#endif // WARN
#ifndef ERROR
#define ERROR(args...) nb::logger.error(args, __FILE__, __LINE__)
#endif // ERROR
#else
#ifndef LOG
#define LOG(args...) nb::logger.log(args)
#endif // LOG
#ifndef WARN
#define WARN(args...) nb::logger.warn(args)
#endif // WARN
#ifndef ERROR
#define ERROR(args...) nb::logger.error(args)
#endif // ERROR
#endif // _NB_CODE_ERROR_LOCATIONS
#endif // _NB_AUTOLOG
#ifndef THROW
#ifdef _NB_AUTOLOG
#define THROW(args...) ERROR(args); throw args
#else
#define THROW(args...) throw args
#endif // _NB_CODE_ERROR_LOCATIONS
#endif // THROW
#endif // _NB_ERROR

View File

@ -9,13 +9,15 @@
#include <vector>
#include "DataSink.hpp"
#include "Errors.hpp"
#include "Processes.hpp"
#include "ThreadSafeQueue.hpp"
#include "TypeTraits.hpp"
namespace nb {
template <typename T>
class ErrorBase;
typedef std::chrono::time_point<
std::chrono::system_clock,
std::chrono::nanoseconds
@ -131,7 +133,10 @@ public:
U val,
std::string file="",
unsigned int line=0
) { static_cast<LoggerType*>(this)->log(val, 0xFF, file, line); }
) {
static_cast<LoggerType*>(this)->log(val, 0xFF, file, line);
static_cast<LoggerType*>(this)->flush();
}
protected:
std::vector<std::ostream*> _ostream;
@ -167,103 +172,6 @@ extern DefaultDebugLogger logger;
// Taking Charge of Adult ADHD by Russell Barkley
/* template <typename T=NoneType>
struct NB_DEFAULT_LOGGER_THROW;
template<>
struct NB_DEFAULT_LOGGER_THROW<NoneType> {
template <typename T>
NB_DEFAULT_LOGGER_THROW(T arg) {
#ifdef _NB_AUTOLOG
logger.error(arg);
#endif // _NB_AUTLOG
throw arg;
}
};
template <typename T>
struct NB_DEFAULT_LOGGER_THROW {
template <typename... Args>
NB_DEFAULT_LOGGER_THROW(Args&&... args) {
std::shared_ptr<T> error_ptr;
#ifdef _NB_AUTOLOG
#ifdef _NB_CODE_ERROR_LOCATIONS
error_ptr = std::make_shared<T>(args..., __LINE__, __FILE__);
#else
error_ptr = std::make_shared<T>(args...);
#endif // _NB_CODE_ERROR_LOCATIONS
logger.error(*error_ptr);
#endif // _NB_AUTLOG
throw *error_ptr;
}
}; */
/* template <typename Arg1=NoneType, typename...Args>
void NB_DEFAULT_LOGGER_THROW(Args&& ... args) {
std::shared_ptr<Arg1> error_ptr;
#ifdef _NB_AUTOLOG
#ifdef _NB_CODE_ERROR_LOCATIONS
error_ptr = std::make_shared<Arg1>(args..., __LINE__, __FILE__);
#else
error_ptr = std::make_shared<Arg1>(args...);
#endif // _NB_CODE_ERROR_LOCATIONS
logger.error(*error_ptr);
#endif // _NB_AUTLOG
throw *error_ptr;
}
template <typename Arg>
void NB_DEFAULT_LOGGER_THROW<NoneType>(const Arg& arg) {
#ifdef _NB_AUTOLOG
logger.error(arg);
#endif // _NB_AUTLOG
throw arg;
} */
template <typename T>
void NB_DEFAULT_LOGGER_THROW(const T& err, std::string file="", unsigned int line = 0) {
#ifdef _NB_AUTOLOG
if (file.empty()) {
logger.error(err);
} else {
logger.error(err, file, line);
}
#endif // _NB_AUTLOG
throw err;
}
} // namespace nb
#ifdef _NB_AUTOLOG
#ifdef _NB_CODE_ERROR_LOCATIONS
#ifndef LOG
#define LOG(args...) nb::logger.log(args, __FILE__, __LINE__)
#endif // LOG
#ifndef WARN
#define WARN(args...) nb::logger.warn(args, __FILE__, __LINE__)
#endif // WARN
#ifndef ERROR
#define ERROR(args...) nb::logger.error(args, __FILE__, __LINE__)
#endif // ERROR
#else
#ifndef LOG
#define LOG(args...) nb::logger.log(args)
#endif // LOG
#ifndef WARN
#define WARN(args...) nb::logger.warn(args)
#endif // WARN
#ifndef ERROR
#define ERROR(args...) nb::logger.error(args)
#endif // ERROR
#endif // _NB_CODE_ERROR_LOCATIONS
#endif // _NB_AUTOLOG
#ifndef THROW
#ifdef _NB_AUTOLOG
#define THROW(args...) ERROR(args); throw args
#else
#define THROW(args...) throw args
#endif // _NB_CODE_ERROR_LOCATIONS
#endif // THROW
#endif // _NB_LOGGER

View File

@ -7,6 +7,8 @@
namespace nb {
uint64_t GetPID();
uint64_t getTID();
} // namespace nb

View File

@ -1,6 +1,6 @@
#pragma once
#ifndef _NB_CORE_TYPES
#define _NB_CORE_TYPES
#ifndef _NB_STRING_UTILS
#define _NB_STRING_UTILS
#include <iostream>
#include <string>
@ -76,4 +76,4 @@ std::string indent_strblock(
);
} // namespace nb
#endif // _NB_CORE_TYPES
#endif // _NB_STRING_UTILS

View File

@ -2,23 +2,79 @@
#ifndef _NB_CORE_TYPES
#define _NB_CORE_TYPES
#include <mutex>
#include <vector>
#include "Errors.hpp"
namespace nb {
/* template<typename T>
T swap_endian(const T& val) {
T ret;
const int size = sizeof(T);
auto retLoc = static_cast<void*>(&ret);
auto valLoc = static_cast<const void*>(&val);
using ByteVector = std::vector<uint8_t>;
for (int i = 0; i < size; ++i) {
memcpy(retLoc+i, valLoc+(size-i-1), 1);
class ObjectManagerError : public Error<ObjectManagerError> {
using Base = Error<ObjectManagerError>;
public:
using Base::Base;
enum Codes : unsigned int {
UNDEFINED, NO_MANAGER, MANAGER_MISMATCH, LOCK_OVERFLOW, BAD_THREAD
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
template <typename T>
class ThreadsafeObjectLock;
template <typename T>
class ThreadsafeObject {
using Codes = ObjectManagerError::Codes;
public:
ThreadsafeObject(T&& obj)
: _obj(std::make_shared<T>(obj)) {}
ThreadsafeObjectLock<T> lock() {
return ThreadsafeObjectLock<T>(this);
}
return ret;
} */
friend ThreadsafeObjectLock<T>;
// using ByteVector = std::vector<uint8_t>;
protected:
std::shared_ptr<T> _obj;
mutable std::recursive_mutex _mutex;
};
template <typename T>
class ThreadsafeObjectLock {
public:
ThreadsafeObjectLock(const ThreadsafeObjectLock&) = delete;
ThreadsafeObjectLock operator=(const ThreadsafeObjectLock&) = delete;
~ThreadsafeObjectLock() {
_manager->_mutex.unlock();
}
T* operator->() {
return _manager->_obj.get();
}
friend ThreadsafeObject<T>;
protected:
ThreadsafeObjectLock(
ThreadsafeObject<T>* const manager_
) : _manager(manager_) {
if (!_manager) {
using Codes = ObjectManagerError::Codes;
THROW(ObjectManagerError(Codes::NO_MANAGER));
}
_manager->_mutex.lock();
}
ThreadsafeObject<T>* const _manager;
};
} // namespace nb
#endif // _NB_CORE_TYPES

View File

@ -33,8 +33,6 @@ static bool RUN_LOGGER(nb::DefaultDebugLogger& log) {
return log.run();
}
static const bool LOGGER_RUNNING = RUN_LOGGER(logger);
} // namespace nb

View File

@ -15,8 +15,15 @@ uint64_t GetPID() {
return GetCurrentProcessId();
}
#endif // _NB_TARGET_WINDOWS
#ifdef _NB_TARGET_LINUX
#endif // _NB_TARGET_LINUX
#ifdef _NB_TARGET_WINDOWS
uint64_t GetTID() {
return GetCurrentThreadId();
}
#endif // _NB_TARGET_WINDOWS
#ifdef _NB_TARGET_LINUX
#endif // _NB_TARGET_LINUX
} // namespace nb

View File

@ -1 +1,27 @@
#include "Utils.hpp"
namespace nb {
using ObjectManagerCodes = ObjectManagerError::Codes;
const std::string ObjectManagerError::type = "nb::ObjectManagerError";
const ErrorCodeMap ObjectManagerError::ErrorMessages({
{ObjectManagerCodes::UNDEFINED, "Error"},
{
ObjectManagerCodes::NO_MANAGER,
"Attempting to create object lock without lock manager"
},
{
ObjectManagerCodes::MANAGER_MISMATCH,
"Attempting to delete object lock from mismatched lock manager"
},
{
ObjectManagerCodes::LOCK_OVERFLOW,
"Too many object locks allocated"
},
{
ObjectManagerCodes::BAD_THREAD,
"Attempting operation from a bad thread"
}
});
}; // namespace nb

View File

@ -5,30 +5,4 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <string>
namespace NB {
static unsigned int __NB_GL_DEBUG_ERROR_CODE__;
static std::string formatDebugString(const std::string& msg, const std::string& file="", int line=-1) {
std::string ret = "";
if (file != "") {
ret += "In file " + file;
if (line >= 0) {
ret += " at line " + std::to_string(line);
}
ret += ":\n\t";
}
return ret + msg;
}
}
#define NB_GL_DEBUG_THROW(cmd, when) while(NB::__NB_GL_DEBUG_ERROR_CODE__=glGetError()){\
std::cout << "[GL ERROR]: " << NB::__NB_GL_DEBUG_ERROR_CODE__;\
std::cout << " " << when << " " << cmd << "\n";\
}
#define NB_GL_DEBUG(cmd) NB_GL_DEBUG_THROW(#cmd, "before"); cmd; NB_GL_DEBUG_THROW(#cmd, "after");
#endif

View File

@ -25,7 +25,11 @@ struct VertexAttribute {
VertexAttributeLayout layout;
};
struct VertexAttributePointer;
struct VertexAttributePointer {
VertexAttribute attribute;
GLuint buffer;
GLuint index;
};
static bool isIndexInVertexAttribute(int i, const VertexAttribute& va) {
if ((i -= va.layout.offset) < 0) { return false; }
@ -85,12 +89,6 @@ class VertexBuffer<true>
};
struct VertexAttributePointer {
VertexAttribute attribute;
VertexBuffer<false>* buffer;
GLuint index;
};
class VAO : public OpenGLObject {
using Base = OpenGLObject;
using Codes = VAOError::Codes;

View File

@ -9,6 +9,7 @@
#include <stdexcept>
#include <string>
#include <NBCore/Errors.hpp>
#include <NBCore/Utils.hpp>
namespace nb {
@ -18,9 +19,32 @@ public:
GLError(const std::string&);
};
class WindowError : public std::runtime_error {
public:
WindowError(const std::string&);
class OpenGLError : public Error<OpenGLError> {
using Base = Error<OpenGLError>;
public:
using Base::Base;
enum Codes : unsigned int {
UNDEFINED, INIT_FAILED, GLFW_INTIALIZED, GLAD_FAILED
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
class WindowError : public Error<WindowError> {
using Base = Error<WindowError>;
public:
using Base::Base;
enum Codes : unsigned int {
UNDEFINED, INITIALIZED_WINDOW, NO_GLFW, INIT_FAILED
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
class Window {

View File

@ -38,7 +38,7 @@ VertexAttributePointerList VAO::attributes(const VertexAttributePointerList& att
_attrs = attrs_;
bind();
for (auto attr_ptr : attrs_) {
attr_ptr.buffer->bind();
glBindBuffer(GL_ARRAY_BUFFER, attr_ptr.buffer);
GLuint idx = attr_ptr.index;
glVertexAttribPointer(
idx,
@ -124,7 +124,7 @@ size_t VertexGroup::buffer(VertexBuffer<false>&& buf_) {
GLuint idx = attrs.size();
for (auto attr : buf_ptr->attributes) {
attrs.emplace_back(
VertexAttributePointer{attr, buf_ptr,idx}
VertexAttributePointer{attr, buf_ptr->id(),idx}
);
idx++;
}
@ -152,7 +152,7 @@ size_t VertexGroup::buffers(std::vector<VertexBuffer<false>>&& bufs_) {
for (auto buf : _vertex_data) {
for (auto attr : buf->attributes) {
attr_ptrs.emplace_back(
VertexAttributePointer{attr, buf.get(), idx}
VertexAttributePointer{attr, buf->id(), idx}
);
idx++;
}
@ -197,10 +197,10 @@ void VertexGroup::disableAttr(GLuint idx) {
}
void VertexGroup::disableBuffer(size_t idx) {
auto buf_ptr = _vertex_data[idx].get();
auto buf_idx = _vertex_data[idx]->id();
bind();
for (auto attr : _vao.attributes()) {
if (attr.buffer == buf_ptr) {
if (attr.buffer == buf_idx) {
_vao.disable(attr.index);
}
}
@ -208,10 +208,10 @@ void VertexGroup::disableBuffer(size_t idx) {
}
void VertexGroup::enableBuffer(size_t idx) {
auto buf_ptr = _vertex_data[idx].get();
auto buf_idx = _vertex_data[idx]->id();
bind();
for (auto attr : _vao.attributes()) {
if (attr.buffer == buf_ptr) {
if (attr.buffer == buf_idx) {
_vao.enable(attr.index);
}
}

View File

@ -16,9 +16,25 @@ static std::map<int, int> defailt_window_hints = {
#endif
};
GLError::GLError(const std::string& msg) : std::runtime_error(msg) {}
using OpenGLErrorCodes = OpenGLError::Codes;
const std::string OpenGLError::type = "nb::OpenGLError";
const ErrorCodeMap OpenGLError::ErrorMessages = {
{OpenGLErrorCodes::UNDEFINED, "Error"},
{OpenGLErrorCodes::INIT_FAILED, "GLFW initialization failed"},
{OpenGLErrorCodes::GLFW_INTIALIZED, "GLFW has already been initialized"},
{OpenGLErrorCodes::GLAD_FAILED, "GLAD initialization failed"}
};
WindowError::WindowError(const std::string &msg) : std::runtime_error(msg) {}
using WindowErrorCodes = WindowError::Codes;
const std::string WindowError::type = "nb::WindowError";
const ErrorCodeMap WindowError::ErrorMessages = {
{WindowErrorCodes::UNDEFINED, "Error"},
{WindowErrorCodes::INITIALIZED_WINDOW, "Window already initialized"},
{WindowErrorCodes::NO_GLFW, "GLFW has not been initialized"},
{WindowErrorCodes::INIT_FAILED, "Could not intialized window"}
};
GLError::GLError(const std::string& msg) : std::runtime_error(msg) {}
int Window::getGLFWHint(int hint_key) {
if (GLFWHints.find(hint_key) == GLFWHints.end()) {
@ -30,7 +46,7 @@ int Window::getGLFWHint(int hint_key) {
int Window::setGLFWHint(int hint_key, int hint_val) {
if (Window::_glfw_init) {
throw GLError("Cannot set GLFW hint after window is initialized.");
THROW(OpenGLError(OpenGLErrorCodes::GLFW_INTIALIZED));
} else {
GLFWHints[hint_key] = hint_val;
}
@ -60,7 +76,7 @@ Window::Window(const uint16_t x, const uint16_t y, const char* initName, GLFWmon
Window::_glfw_init = true;
} else {
if (Window::StrictInitialization) {
throw GLError("Failed to load GLFW with glfwInit()="+std::to_string(glfwResponse)+".");
THROW(OpenGLError(OpenGLErrorCodes::INIT_FAILED));
}
}
}
@ -103,7 +119,7 @@ int Window::getWindowHint(int hint_key) const {
int Window::setWindowHint(int hint_key, int hint_val) {
if (_init) {
throw WindowError("Cannot set window hint after window is initialized.");
THROW(WindowError(WindowErrorCodes::INITIALIZED_WINDOW));
} else {
windowHints[hint_key] = hint_val;
}
@ -112,7 +128,7 @@ int Window::setWindowHint(int hint_key, int hint_val) {
int Window::init() {
if (!_glfw_init) {
throw GLError("GLFW has not been initialized.");
THROW(WindowError(WindowErrorCodes::NO_GLFW));
}
for (const auto& hint : windowHints) {
glfwWindowHint(hint.first, hint.second);
@ -123,7 +139,7 @@ int Window::init() {
Window::WindowContexts.erase(window);
if (Window::WindowContexts.size()==0 && Window::_glfw_init) { glfwTerminate(); }
if (Window::StrictInitialization) {
throw WindowError("Could not create window in glfwCreateWindow().");
THROW(WindowError(WindowErrorCodes::INIT_FAILED));
}
}
glfwMakeContextCurrent(window);
@ -133,10 +149,7 @@ int Window::init() {
if (!gladResponse) {
Window::checkKillGLFW();
if (Window::StrictInitialization) {
throw GLError("Failed to load GLAD with \
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)="+\
std::to_string(gladResponse)+"."
);
THROW(OpenGLError(OpenGLErrorCodes::GLAD_FAILED));
}
}

View File

@ -9,8 +9,8 @@ if (NB_BUILD_TESTS)
target_link_libraries(TestWindow
NBCore
NBGraphics
GTest::gtest_main
# GTest::gtest_main
)
gtest_discover_tests(TestWindow)
# gtest_discover_tests(TestWindow)
endif()

View File

@ -1,6 +1,18 @@
#include <Buffers.hpp>
#include "GLLoad.hpp"
// #define _NB_AUTOLOG
#include "VertexArray.hpp"
#include "Window.hpp"
int main() {
nb::logger.log("Howdy!");
nb::Window window(200, 200, "Hello!");
window.setWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
window.setWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
window.init();
GLFWwindow* window_ptr = window.getWindow();
while(!glfwWindowShouldClose(window_ptr)) {}
return 0;
}