diff --git a/include/uui/opengl/application.hpp b/include/uui/opengl/application.hpp index 9601f56..32d6c28 100644 --- a/include/uui/opengl/application.hpp +++ b/include/uui/opengl/application.hpp @@ -26,10 +26,11 @@ public: ~GlApplication(); void run(); - std::weak_ptr create_window(int width, int height, const std::string& title); + std::shared_ptr create_window(int width, int height, const std::string& title); + std::shared_ptr get_window(size_t index) const; private: - static bool application_created; + static GlApplication* application_pointer; }; class GlComponent; @@ -46,22 +47,28 @@ public: GlWindow(GlWindow&&) = delete; ~GlWindow(); - std::weak_ptr create_component( + std::shared_ptr create_component( const std::variant x, const std::variant y, const std::variant width, const std::variant height); private: - const GlApplication& app; + GlApplication* app; int width; int height; + bool need_resize_refresh; + + size_t index; + bool initialized; GLFWwindow* glfw_window; GLuint gl_program; - GlWindow(const GlApplication& app, int width, int height, const std::string& title); + GlWindow(GlApplication* app, size_t index, int width, int height, const std::string& title); + void init(); + void deinit(); void draw(); static void glfw_resize_callback(GLFWwindow* window, int width, int height); diff --git a/include/uui/opengl/component.hpp b/include/uui/opengl/component.hpp index 1385ecb..c7b05b2 100644 --- a/include/uui/opengl/component.hpp +++ b/include/uui/opengl/component.hpp @@ -18,16 +18,16 @@ public: GlComponent(GlComponent&&) = delete; ~GlComponent(); - void render(); + void set_background_color(float r, float g, float b, float a = 0.0f); private: - // std::weak_ptr window; - GlWindow* window; + std::shared_ptr window; std::variant position_x; std::variant position_y; std::variant size_width; std::variant size_height; + bool coord_all_relative; std::array background_color; @@ -38,11 +38,14 @@ private: GLuint gl_ebo; GlComponent( - GlWindow* window, const std::variant x, const std::variant y, + std::shared_ptr window, const std::variant x, const std::variant y, const std::variant width, const std::variant height); void init(); + void set_vbo_data(); void deinit(); + void render(); + void on_resize(); }; } // namespace uui diff --git a/make.py b/make.py index 8cabbf7..63adb60 100644 --- a/make.py +++ b/make.py @@ -4,7 +4,7 @@ import os from pathlib import Path import shutil -from umake import make +from umake import get_hash, make class Config: @@ -31,17 +31,32 @@ class Config: def main(): def pre_compile(): +<<<<<<< HEAD +======= + # Compiling vulkan shaders + # for shader_path in ( + # list((Config.SOURCE_DIR / 'uui' / 'vulkan').rglob('*.vert')) + # + list((Config.SOURCE_DIR / 'uui' / 'vulkan').rglob('*.frag'))): + # out_path = Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR) + # if not out_path.parent.exists(): + # out_path.parent.mkdir(parents=True) + # if subprocess.run(['glslc', str(shader_path), '-o', str(out_path) + '.spv']).returncode != 0: + # print(f'Error while compiling shader {shader_path}') + # return +>>>>>>> 675cbbf (Correct resize and safer pointers) # Copying OpenGL shaders src_opengl_shader_path = Config.SOURCE_DIR / 'uui' / 'opengl' / 'shaders' for shader_path in ( list(src_opengl_shader_path.rglob('*.vert')) + list(src_opengl_shader_path.rglob('*.frag'))): out_path = Config.BIN_DIR / shader_path.relative_to(Config.SOURCE_DIR) + if out_path.exists() and get_hash(shader_path) == get_hash(out_path): + continue if not out_path.parent.exists(): out_path.parent.mkdir(parents=True) shutil.copy(shader_path, out_path) - # Config.PRE_COMPILE_FUNCTION = pre_compile + Config.PRE_COMPILE_FUNCTION = pre_compile make(Config) diff --git a/src/test/example_gl.cpp b/src/test/example_gl.cpp index 043d374..4b3c9d5 100644 --- a/src/test/example_gl.cpp +++ b/src/test/example_gl.cpp @@ -7,24 +7,28 @@ using namespace std; int main() { - cout << "Example Staring" << endl; - try { + cout << "Starting example 1" << endl; { uui::GlApplication app; // uui::GlApplication app2; // exception : application already created - auto window_1 = app.create_window(800, 600, "OpenGl!"); - window_1.lock()->create_component(0, 1, 0.5f, 50); + auto window = app.create_window(800, 600, "OpenGl!"); + auto comp = window->create_component(0, 100, 0.5f, 50); + comp->set_background_color(0.8f, 0.1f, 0.5f); app.run(); } + cout << "\nStarting example 2" << endl; { uui::GlApplication app; auto window_1 = app.create_window(800, 600, "OpenGl!"); - window_1.lock()->create_component(0.25f, 0.25f, 0.5f, 0.5f); - window_1.lock()->create_component(0.75f, 0.75f, 0.25f, 0.25f); + auto comp = window_1->create_component(0.25f, 0.25f, 0.5f, 0.5f); + comp->set_background_color(0.8f, 0.1f, 0.5f); + comp = window_1->create_component(0.75f, 0.75f, 0.25f, 0.25f); + comp->set_background_color(0.2f, 0.1f, 0.5f); auto window_2 = app.create_window(600, 600, "OpenGL 2!"); - window_2.lock()->create_component(0, 0.5f, 100, 0.5f); + comp = window_2->create_component(0, 0.5f, 100, 0.5f); + comp->set_background_color(0.2f, 0.5f, 0.3f); app.run(); } } diff --git a/src/uui/opengl/application.cpp b/src/uui/opengl/application.cpp index 9d4857b..1bb18a9 100644 --- a/src/uui/opengl/application.cpp +++ b/src/uui/opengl/application.cpp @@ -3,11 +3,11 @@ #include #include -bool uui::GlApplication::application_created = false; +uui::GlApplication* uui::GlApplication::application_pointer = nullptr; uui::GlApplication::GlApplication() { - if(application_created) + if(application_pointer != nullptr) throw std::runtime_error("GlApplication error: the application already created"); if constexpr(debug_mode) std::cout << "Creating the GlApplication in debug mode" << std::endl; @@ -23,7 +23,7 @@ uui::GlApplication::GlApplication() if constexpr(uui::GlApplication::debug_mode) glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); - application_created = true; + application_pointer = this; } uui::GlApplication::~GlApplication() @@ -31,7 +31,7 @@ uui::GlApplication::~GlApplication() std::cout << "Destroying the GlApplication" << std::endl; windows.clear(); glfwTerminate(); - application_created = false; + application_pointer = nullptr; } void uui::GlApplication::run() @@ -67,6 +67,7 @@ void uui::GlApplication::run() glfwMakeContextCurrent((*(windows.end() - 2))->glfw_window); glfwSwapInterval(1); } + window->deinit(); windows.erase(it); it -= 1; } @@ -78,9 +79,10 @@ void uui::GlApplication::run() std::cout << "Ending the GlApplication" << std::endl; } -std::weak_ptr uui::GlApplication::create_window(int width, int height, const std::string& title) +std::shared_ptr uui::GlApplication::create_window(int width, int height, const std::string& title) { - std::shared_ptr window(new uui::GlWindow(*this, width, height, title)); + std::shared_ptr window(new uui::GlWindow(this, windows.size(), width, height, title)); + window->init(); windows.push_back(window); glfwSwapInterval(1); if(windows.size() > 1) @@ -90,3 +92,10 @@ std::weak_ptr uui::GlApplication::create_window(int width, int he } return window; } + +std::shared_ptr uui::GlApplication::get_window(size_t index) const +{ + if(index > windows.size()) + throw std::runtime_error("Application doesn't have window at given index"); + return windows[index]; +} diff --git a/src/uui/opengl/component.cpp b/src/uui/opengl/component.cpp index f8267fc..242ad3e 100644 --- a/src/uui/opengl/component.cpp +++ b/src/uui/opengl/component.cpp @@ -6,21 +6,27 @@ #include "uui/opengl/gl_utils.hpp" uui::GlComponent::GlComponent( - GlWindow* window, const std::variant x, const std::variant y, + std::shared_ptr window, const std::variant x, const std::variant y, const std::variant width, const std::variant height): window(window), position_x(x), position_y(y), size_width(width), size_height(height), initialized(false) { std::cout << "Creating a GlBox" << std::endl; - auto zero_to_float = [](std::variant& value) { - if(value.index() == 0 && std::get<0>(value) == 0) - value = 0.0f; + coord_all_relative = true; + auto parse_coords = [&](std::variant& value) { + if(value.index() == 0) + { + if(std::get<0>(value) == 0) + value = 0.0f; + else + coord_all_relative = false; + } }; - zero_to_float(position_x); - zero_to_float(position_y); - zero_to_float(size_width); - zero_to_float(size_height); + parse_coords(position_x); + parse_coords(position_y); + parse_coords(size_width); + parse_coords(size_height); background_color = {0.0f, 0.0f, 0.0f, 0.0f}; } @@ -32,6 +38,14 @@ uui::GlComponent::~GlComponent() deinit(); } +void uui::GlComponent::set_background_color(float r, float g, float b, float a) +{ + background_color = {r, g, b, a}; + glBindVertexArray(gl_vao); + set_vbo_data(); + glBindVertexArray(0); // Optional : for safety +} + void uui::GlComponent::init() { if(initialized) @@ -45,44 +59,7 @@ void uui::GlComponent::init() if constexpr(uui::GlApplication::debug_mode) _glCheckError(); - { - float vert_x = position_x.index() == 1 ? std::get<1>(position_x) - : static_cast(std::get<0>(position_x)) / static_cast(window->width); - float vert_y = position_y.index() == 1 ? std::get<1>(position_y) - : static_cast(std::get<0>(position_y)) / static_cast(window->height); - float vert_w = size_width.index() == 1 ? std::get<1>(size_width) - : static_cast(std::get<0>(size_width)) / static_cast(window->width); - float vert_h = size_height.index() == 1 ? std::get<1>(size_height) - : static_cast(std::get<0>(size_height)) / static_cast(window->height); - float x_min = (2.0f * vert_x) - 1.0f; - float x_max = x_min + (2.0f * vert_w); - float y_min = (-2.0f * vert_y) + 1.0f; - float y_max = y_min - (2.0f * vert_h); - // clang-format off - float vertices[] = { - x_max, y_min, 0.0f, // top right - x_max, y_max, 0.0f, // bottom right - x_min, y_max, 0.0f, // bottom left - x_min, y_min, 0.0f // top left - }; - // clang-format on - glBindBuffer(GL_ARRAY_BUFFER, gl_vbo); - if constexpr(uui::GlApplication::debug_mode) - _glCheckError(); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - if constexpr(uui::GlApplication::debug_mode) - _glCheckError(); - } - - glVertexAttribPointer( - 0, // index - 3, // size - GL_FLOAT, // type - GL_FALSE, // enable normalization, - 3 * sizeof(float), // stride - (void*)0 // offset - ); - glEnableVertexAttribArray(0); + set_vbo_data(); unsigned int indices[] = { 0, 1, 3, // first triangle @@ -102,6 +79,55 @@ void uui::GlComponent::init() initialized = true; } +void uui::GlComponent::set_vbo_data() +{ + float vert_x = + position_x.index() == 1 ? std::get<1>(position_x) : static_cast(std::get<0>(position_x)) / static_cast(window->width); + float vert_y = + position_y.index() == 1 ? std::get<1>(position_y) : static_cast(std::get<0>(position_y)) / static_cast(window->height); + float vert_w = + size_width.index() == 1 ? std::get<1>(size_width) : static_cast(std::get<0>(size_width)) / static_cast(window->width); + float vert_h = size_height.index() == 1 ? std::get<1>(size_height) + : static_cast(std::get<0>(size_height)) / static_cast(window->height); + float x_min = (2.0f * vert_x) - 1.0f; + float x_max = x_min + (2.0f * vert_w); + float y_min = (-2.0f * vert_y) + 1.0f; + float y_max = y_min - (2.0f * vert_h); + // clang-format off + float vertices[] = { + x_max, y_min, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3], // top right + x_max, y_max, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3], // bottom right + x_min, y_max, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3], // bottom left + x_min, y_min, 0.0f, background_color[0] , background_color[1], background_color[2], background_color[3] // top left + }; + // clang-format on + glBindBuffer(GL_ARRAY_BUFFER, gl_vbo); + if constexpr(uui::GlApplication::debug_mode) + _glCheckError(); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + if constexpr(uui::GlApplication::debug_mode) + _glCheckError(); + + glVertexAttribPointer( + 0, // index + 3, // size + GL_FLOAT, // type + GL_FALSE, // enable normalization, + 7 * sizeof(float), // stride + (void*)0 // offset + ); + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 1, // index + 3, // size + GL_FLOAT, // type + GL_FALSE, // enable normalization, + 7 * sizeof(float), // stride + (void*)(3 * sizeof(float)) // offset + ); + glEnableVertexAttribArray(1); +} + void uui::GlComponent::deinit() { if(!initialized) @@ -120,3 +146,13 @@ void uui::GlComponent::render() if constexpr(uui::GlApplication::debug_mode) _glCheckError(); } + +void uui::GlComponent::on_resize() +{ + if(!coord_all_relative) + { + glBindVertexArray(gl_vao); + set_vbo_data(); + glBindVertexArray(0); // Optional : for safety + } +} diff --git a/src/uui/opengl/shaders/main.frag b/src/uui/opengl/shaders/main.frag index 78f4aca..58aeffd 100644 --- a/src/uui/opengl/shaders/main.frag +++ b/src/uui/opengl/shaders/main.frag @@ -2,7 +2,9 @@ out vec4 FragColor; +in vec4 backgroundColor; + void main() { - FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); + FragColor = backgroundColor; } diff --git a/src/uui/opengl/shaders/main.vert b/src/uui/opengl/shaders/main.vert index 234598a..68139d6 100644 --- a/src/uui/opengl/shaders/main.vert +++ b/src/uui/opengl/shaders/main.vert @@ -1,8 +1,12 @@ #version 460 core -layout (location = 0) in vec3 aPos; +layout (location = 0) in vec3 vPos; +layout (location = 1) in vec4 vBackgroundColor; + +out vec4 backgroundColor; void main() { - gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); + gl_Position = vec4(vPos.x, vPos.y, vPos.z, 1.0); + backgroundColor = vBackgroundColor; } diff --git a/src/uui/opengl/window.cpp b/src/uui/opengl/window.cpp index 85b8512..197a605 100644 --- a/src/uui/opengl/window.cpp +++ b/src/uui/opengl/window.cpp @@ -55,9 +55,10 @@ void uui::GlWindow::glfw_resize_callback(GLFWwindow* window, int width, int heig { glfwMakeContextCurrent(window); auto gl_window = reinterpret_cast(glfwGetWindowUserPointer(window)); + glViewport(0, 0, width, height); gl_window->width = width; gl_window->height = height; - glViewport(0, 0, width, height); + gl_window->need_resize_refresh = true; } static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) @@ -66,11 +67,27 @@ static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int act glfwSetWindowShouldClose(window, true); } -uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, const std::string& title): - app(app), width(width), height(height) +uui::GlWindow::GlWindow(uui::GlApplication* app, size_t index, int width, int height, const std::string& title): + app(app), width(width), height(height), need_resize_refresh(false), index(index), initialized(false) { std::cout << "Creating a GlWindow" << std::endl; this->title = title; +} + +uui::GlWindow::~GlWindow() +{ + std::cout << "Closing a GlWindow" << std::endl; + if(initialized) + { + std::cout << "Destructor-deinit a GlWindow" << std::endl; + deinit(); + } +} + +void uui::GlWindow::init() +{ + if(initialized) + throw std::runtime_error("GlWindow error : calling init while already initialized"); glfw_window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); if(glfw_window == NULL) @@ -161,15 +178,23 @@ uui::GlWindow::GlWindow(const uui::GlApplication& app, int width, int height, co } glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); + initialized = true; } -uui::GlWindow::~GlWindow() +void uui::GlWindow::deinit() { - std::cout << "Closing a GlWindow" << std::endl; + if(!initialized) + throw std::runtime_error("GlWindow error : calling deinit while not initialized"); + + std::cout << "Deinit a GlWindow" << std::endl; + glfwMakeContextCurrent(glfw_window); glDeleteProgram(gl_program); + for(auto& component: components) component->deinit(); components.clear(); glfwDestroyWindow(glfw_window); + + initialized = false; } void uui::GlWindow::draw() @@ -179,18 +204,25 @@ void uui::GlWindow::draw() glClear(GL_COLOR_BUFFER_BIT); glUseProgram(gl_program); + if(need_resize_refresh) + { + for(auto& component: components) component->on_resize(); + need_resize_refresh = false; + } for(auto& component: components) component->render(); glfwSwapBuffers(glfw_window); } -std::weak_ptr uui::GlWindow::create_component( +std::shared_ptr uui::GlWindow::create_component( const std::variant x, const std::variant y, const std::variant width, const std::variant height) { + if(!initialized) + throw std::runtime_error("GlWindow error : cannot create component while not initialized"); + glfwMakeContextCurrent(glfw_window); - // std::shared_ptr self_ptr(this); - std::shared_ptr component(new uui::GlComponent(this, x, y, width, height)); + std::shared_ptr component(new uui::GlComponent(app->get_window(index), x, y, width, height)); component->init(); components.push_back(component); return component;