window system, glfw, imgui

This commit is contained in:
L-Nafaryus 2022-10-28 21:16:03 +05:00
parent 38c644ffdf
commit cb07c61b7f
21 changed files with 453 additions and 94 deletions

View File

@ -7,8 +7,6 @@ project(
LANGUAGES CXX LANGUAGES CXX
) )
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
option(WITH_GTESTS "Enable GTest unit testing" ON) option(WITH_GTESTS "Enable GTest unit testing" ON)
@ -21,6 +19,10 @@ endif()
include(${CMAKE_SOURCE_DIR}/cmake/glad.cmake) include(${CMAKE_SOURCE_DIR}/cmake/glad.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/imgui.cmake)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
add_definitions(-DPRECISION_FLOAT) add_definitions(-DPRECISION_FLOAT)
add_subdirectory(source) add_subdirectory(source)

86
cmake/imgui.cmake Normal file
View File

@ -0,0 +1,86 @@
include(${CMAKE_CURRENT_LIST_DIR}/CPM.cmake)
# branch: docking
CPMAddPackage(
NAME imgui_external
GIT_REPOSITORY https://github.com/ocornut/imgui.git
GIT_TAG 24dfebf455ac1f7685e1a72272d37b72601fe70c
DOWNLOAD_ONLY YES
)
if(imgui_external_ADDED)
project(imgui)
set(CMAKE_CXX_STANDARD 17)
find_package(PkgConfig REQUIRED)
find_package(Freetype REQUIRED)
find_package(OpenGL REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_library(${PROJECT_NAME} STATIC
${imgui_external_SOURCE_DIR}/imgui.cpp
${imgui_external_SOURCE_DIR}/imgui_demo.cpp
${imgui_external_SOURCE_DIR}/imgui_draw.cpp
${imgui_external_SOURCE_DIR}/imgui_tables.cpp
${imgui_external_SOURCE_DIR}/imgui_widgets.cpp
${imgui_external_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
${imgui_external_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
${imgui_external_SOURCE_DIR}/misc/freetype/imgui_freetype.cpp
${imgui_external_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp
)
add_library(imgui::imgui ALIAS ${PROJECT_NAME})
add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${imgui_external_SOURCE_DIR}>
$<BUILD_INTERFACE:${imgui_external_SOURCE_DIR}/backends>
$<BUILD_INTERFACE:${imgui_external_SOURCE_DIR}/misc/freetype>
$<BUILD_INTERFACE:${imgui_external_SOURCE_DIR}/misc/cpp>
${FREETYPE_INCLUDE_DIRS}
${GLFW_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
PUBLIC
Freetype::Freetype
glfw
OpenGL::GL
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
POSITION_INDEPENDENT_CODE ON
OUTPUT_NAME imgui
EXCLUDE_FROM_ALL ON
)
include(GNUInstallDirs)
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}
)
install(
EXPORT ${PROJECT_NAME}Targets
FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
install(
DIRECTORY ${imgui_external_SOURCE_DIR}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
COMPONENT devel
FILES_MATCHING
PATTERN "*.h"
PATTERN "*.hpp"
)
endif()

View File

@ -14,4 +14,5 @@ add_executable(hyporo
target_link_libraries(hyporo target_link_libraries(hyporo
PUBLIC PUBLIC
hyporo-hyplib) hyporo-gpu
imgui)

View File

@ -1,22 +1,56 @@
#include "scalar.hpp" #include "../hyporo/gpu/window_system.hpp"
#include "vector.hpp" #include "../hyporo/gpu/glfw/window.hpp"
#include <algorithm> #include <imgui.h>
#include <iostream> #include <imgui_impl_glfw.h>
#include "matrix.hpp" #include <imgui_impl_opengl3.h>
int main(void) int main(void)
{ {
hyporo::vec3 v1 {1, 3, 2}; hpr::gpu::WindowSystem* ws = hpr::gpu::WindowSystem::create(hpr::gpu::WindowContext::Provider::GLFW);
hyporo::vec3 v2 {7, 4, 5}; hpr::gpu::Window* w = ws->newWindow();
std::cout << -v1 << std::endl; w->init("test", hpr::gpu::Window::Style::Windowed, 0, 0, 600, 400, nullptr, nullptr);
std::cout << ((v1 + v2) == hyporo::vec3(8, 7, 7)) << std::endl;
std::cout << v1 - v2 << std::endl; IMGUI_CHECKVERSION();
std::cout << v1 * 2 << std::endl; ImGui::CreateContext();
std::cout << v1 / 2 << std::endl;
std::cout << (v1 == v2) << std::endl; ImGuiIO& io = ImGui::GetIO();
std::cout << (v1 == v1) << std::endl; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
hyporo::mat3 m1 {1, 3, 2, 5, 3, 6, 7, 2, 0}; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
hyporo::mat3 m2 {7, 4, 5, 5, 7, 3, 1, 4, 6};
std::cout << m1 + m2 << std::endl; ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(dynamic_cast<hpr::gpu::glfw::Window*>(w)->instance(), true);
ImGui_ImplOpenGL3_Init("#version 330");
while (w->isOpen())
{
dynamic_cast<hpr::gpu::glfw::Window*>(w)->pollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
bool yes = true;
ImGui::ShowDemoWindow(&yes);
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
{
if (ImGui::Button("Exit")) // Buttons return true when clicked (most widgets return true when edited/activated)
w->state(hpr::gpu::Window::State::Closed);
ImGui::End();
}
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
dynamic_cast<hpr::gpu::glfw::Window*>(w)->swapBuffers();
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
ws->destroyWindow(w);
hpr::gpu::WindowSystem::destroy(ws);
return 0; return 0;
} }

View File

@ -5,35 +5,49 @@ include_directories(
add_library(hyporo-gpu STATIC add_library(hyporo-gpu STATIC
# Source files # Source files
buffer.cpp window_system.cpp
context.cpp monitor.cpp
shader.cpp buffer.cpp
opengl/buffer.cpp context.cpp
opengl/context.cpp shader.cpp
opengl/shader.cpp window.cpp
opengl/texture.cpp opengl/buffer.cpp
opengl/device.cpp opengl/context.cpp
opengl/shader_program.cpp opengl/shader.cpp
texture.cpp opengl/texture.cpp
device.cpp #opengl/device.cpp
shader_program.cpp opengl/shader_program.cpp
texture.cpp
#device.cpp
glfw/window_system.cpp
glfw/monitor.cpp
glfw/window.cpp
shader_program.cpp
# Header files # Header files
context.hpp monitor.hpp
shader.hpp context.hpp
shader_program.hpp shader.hpp
buffer.hpp window_context.hpp
device.hpp shader_program.hpp
texture.hpp buffer.hpp
opengl/context.hpp #device.hpp
opengl/shader.hpp window.hpp
opengl/shader_program.hpp texture.hpp
opengl/buffer.hpp opengl/context.hpp
opengl/device.hpp opengl/shader.hpp
opengl/texture.hpp opengl/shader_program.hpp
opengl/buffer.hpp
#opengl/device.hpp
opengl/texture.hpp
window_system.hpp
glfw/monitor.hpp
glfw/window.hpp
glfw/window_system.hpp
) )
target_link_libraries(hyporo-gpu target_link_libraries(hyporo-gpu
glad glad
glfw
hyporo-hyplib hyporo-hyplib
) )

View File

@ -1,5 +1,14 @@
//
// Created by L-Nafaryus on 10/27/2022.
//
#include "monitor.hpp" #include "monitor.hpp"
namespace hpr::gpu::glfw
{
Monitor::Monitor() :
gpu::Monitor {Provider::GLFW},
p_instance {nullptr}
{}
Monitor::~Monitor() = default;
}

View File

@ -2,12 +2,26 @@
#include "../monitor.hpp" #include "../monitor.hpp"
#include "GLFW/glfw3.h"
namespace hpr::gpu::glfw namespace hpr::gpu::glfw
{ {
class Monitor : public gpu::Monitor class Monitor : public gpu::Monitor
{ {
friend class WindowSystem;
friend class Window;
protected:
GLFWmonitor* p_instance;
public:
Monitor();
~Monitor();
}; };

View File

@ -1,5 +1,100 @@
//
// Created by L-Nafaryus on 10/27/2022.
//
#include "window.hpp" #include "window.hpp"
#include "monitor.hpp"
#include <stdexcept>
namespace hpr::gpu::glfw
{
Window::Window() :
gpu::Window {Provider::GLFW},
p_instance {nullptr}
{}
Window::~Window() = default;
void Window::init(const std::string& title, Style style, int x, int y, int width, int height, gpu::Window* parent, gpu::Monitor* monitor)
{
if (!checkCompability(parent))
throw std::invalid_argument("Incompatible window provider passed");
gpu::Window::init(title, style, x, y, width, height, parent, monitor);
glfw::Window* parent_ = dynamic_cast<glfw::Window*>(parent);
glfw::Monitor* monitor_ = dynamic_cast<glfw::Monitor*>(monitor);
p_instance = glfwCreateWindow(width, height, title.c_str(),
monitor_ != nullptr ? monitor_->p_instance : nullptr, parent_ != nullptr ? parent_->p_instance : nullptr);
if (p_instance == nullptr)
throw std::runtime_error("Cannot create GLFW window");
glfwMakeContextCurrent(p_instance);
glfwSetWindowPos(p_instance, x, y);
this->style(style);
}
void Window::init(const std::string& title, Style style, gpu::Window* parent, gpu::Monitor* monitor)
{
init(title, style, monitor->originX(), monitor->originY(), monitor->width(), monitor->height(), parent, monitor);
}
void Window::state(State state)
{
gpu::Window::state(state);
switch (state)
{
case State::Visible:
glfwShowWindow(p_instance);
break;
case State::Hidden:
glfwHideWindow(p_instance);
break;
case State::Maximized:
glfwMaximizeWindow(p_instance);
break;
case State::Minimized:
glfwIconifyWindow(p_instance);
break;
case State::Closed:
glfwSetWindowShouldClose(p_instance, GLFW_TRUE);
break;
default:
break;
}
}
void Window::close()
{
gpu::Window::close();
glfwDestroyWindow(p_instance);
p_instance = nullptr;
}
void Window::style(Style style)
{
gpu::Window::style(style);
if (style == Style::Windowed)
{
glfwSetWindowMonitor(p_instance, nullptr, p_posX, p_posY, p_width, p_height, GLFW_DONT_CARE);
}
else if (style == Style::Fullscreen)
{
glfwSetWindowMonitor(p_instance, glfwGetPrimaryMonitor(), p_posX, p_posY, p_width, p_height, GLFW_DONT_CARE);
}
else if (style == Style::Popup)
{
//throw std::runtime_error("Popup style is not supported");
}
}
void Window::swapBuffers()
{
glfwSwapBuffers(p_instance);
}
void Window::pollEvents()
{
glfwPollEvents();
}
}

View File

@ -1,8 +1,45 @@
// #pragma once
// Created by L-Nafaryus on 10/27/2022.
//
#ifndef HYPORO_WINDOW_HPP #include "../window.hpp"
#define HYPORO_WINDOW_HPP
#endif //HYPORO_WINDOW_HPP #include <GLFW/glfw3.h>
namespace hpr::gpu::glfw
{
class Window : public gpu::Window
{
friend class WindowSystem;
protected:
GLFWwindow* p_instance;
public:
Window();
virtual
~Window();
GLFWwindow* instance() const
{
return p_instance;
}
void init(const std::string& title, Style style, int x, int y, int width, int height, gpu::Window* parent, gpu::Monitor* monitor) override;
void init(const std::string& title, Style style, gpu::Window* parent, gpu::Monitor* monitor) override;
void state(State state) override;
void close() override;
void style(Style style) override;
void swapBuffers();
void pollEvents();
};
}

View File

@ -1,5 +1,38 @@
// #include "monitor.hpp"
// Created by L-Nafaryus on 10/27/2022. #include "window.hpp"
//
#include "window_system.hpp" #include "window_system.hpp"
namespace hpr::gpu::glfw
{
WindowSystem::WindowSystem() :
gpu::WindowSystem {Provider::GLFW}
{
if (!glfwInit())
throw std::runtime_error("Cannot initialize GLFW");
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}
WindowSystem::~WindowSystem()
{
for (auto& window : p_windows)
window->close();
glfwTerminate();
}
gpu::Window* WindowSystem::newWindow()
{
p_windows.push(new glfw::Window);
return static_cast<gpu::Window*>(p_windows.back());
}
std::function<GLFWglproc(const char*)> WindowSystem::deviceProcAddress() const
{
return std::function<GLFWglproc(const char*)>(glfwGetProcAddress);
}
}

View File

@ -3,6 +3,7 @@
#include "../window_system.hpp" #include "../window_system.hpp"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <functional>
namespace hpr::gpu::glfw namespace hpr::gpu::glfw
@ -11,18 +12,15 @@ namespace hpr::gpu::glfw
class WindowSystem : public gpu::WindowSystem class WindowSystem : public gpu::WindowSystem
{ {
protected:
GLFWwindow p_instance;
public: public:
WindowSystem(); WindowSystem();
~WindowSystem(); ~WindowSystem() override;
virtual gpu::Window* newWindow() override;
void newWindow(Window** window);
std::function<GLFWglproc(const char*)> deviceProcAddress() const;
}; };
} }

View File

@ -15,6 +15,17 @@ Monitor::Monitor() :
p_logicalHeight {0} p_logicalHeight {0}
{} {}
Monitor::Monitor(Provider provider) :
WindowContext(provider),
p_deviceName {},
p_originX {0},
p_originY {0},
p_width {0},
p_height {0},
p_logicalWidth {0},
p_logicalHeight {0}
{}
Monitor::~Monitor() = default; Monitor::~Monitor() = default;
void Monitor::origin(int x, int y) void Monitor::origin(int x, int y)

View File

@ -8,7 +8,7 @@
namespace hpr::gpu namespace hpr::gpu
{ {
class Monitor : WindowContext class Monitor : public WindowContext
{ {
protected: protected:
@ -25,6 +25,8 @@ public:
Monitor(); Monitor();
Monitor(Provider provider);
virtual virtual
~Monitor(); ~Monitor();

View File

@ -14,7 +14,7 @@ ShaderProgram::ShaderProgram() :
ShaderProgram::~ShaderProgram() ShaderProgram::~ShaderProgram()
{} {}
Shader *ShaderProgram::shader(gpu::Shader::ShaderType type) Shader* ShaderProgram::shader(gpu::Shader::ShaderType type)
{ {
return static_cast<opengl::Shader*>(p_slots[(size_t)type]); return static_cast<opengl::Shader*>(p_slots[(size_t)type]);
} }

View File

@ -19,6 +19,21 @@ Window::Window() :
p_isResizing {false} p_isResizing {false}
{} {}
Window::Window(Provider provider) :
WindowContext(provider),
p_width {0},
p_height {0},
p_posX {0},
p_posY {0},
p_title {},
p_state {State::Hidden},
p_style {Style::Unknown},
p_parent {nullptr},
p_monitor {nullptr},
p_isActive {true},
p_isResizing {false}
{}
Window::~Window() = default; Window::~Window() = default;
void Window::init(const std::string& title, Style style, int x, int y, int width, int height, Window* parent, Monitor* monitor) void Window::init(const std::string& title, Style style, int x, int y, int width, int height, Window* parent, Monitor* monitor)

View File

@ -50,6 +50,8 @@ public:
Window(); Window();
Window(Provider provider);
virtual virtual
~Window(); ~Window();
@ -62,7 +64,7 @@ public:
void init(const std::string& title, Style style, Window* parent, Monitor* monitor); void init(const std::string& title, Style style, Window* parent, Monitor* monitor);
virtual virtual
void state(State state = State::Visible); void state(State state);
virtual virtual
void close(); void close();

View File

@ -34,6 +34,11 @@ public:
virtual virtual
~WindowContext() = default; ~WindowContext() = default;
bool checkCompability(const WindowContext* ctx) const
{
return (ctx != nullptr) ? ctx->p_provider == p_provider : true;
}
}; };
} }

View File

@ -15,17 +15,13 @@ WindowSystem::WindowSystem(Provider provider) :
WindowSystem::~WindowSystem() = default; WindowSystem::~WindowSystem() = default;
void WindowSystem::create(WindowSystem** ws, Provider provider) WindowSystem* WindowSystem::create(Provider provider)
{ {
if (ws == nullptr)
throw std::invalid_argument("Invalid parameter 'nullptr'");
if (provider == Provider::Unknown) if (provider == Provider::Unknown)
throw std::invalid_argument("Cannot create window system from 'Unknown' provider"); throw std::invalid_argument("Cannot create window system from 'Unknown' provider");
*ws = nullptr;
if (provider == Provider::GLFW) if (provider == Provider::GLFW)
*ws = new glfw::WindowSystem; return new glfw::WindowSystem;
else else
throw std::invalid_argument("Unsupported window system"); throw std::invalid_argument("Unsupported window system");
} }
@ -36,7 +32,7 @@ void WindowSystem::destroy(WindowSystem*& ws)
ws = nullptr; ws = nullptr;
} }
Window& WindowSystem::window(int index) Window* WindowSystem::window(int index)
{ {
return p_windows[index]; return p_windows[index];
} }
@ -48,16 +44,18 @@ void WindowSystem::closeWindow(Window* window)
void WindowSystem::destroyWindow(Window* window) void WindowSystem::destroyWindow(Window* window)
{ {
p_windows.remove(*window); p_windows.remove(window);
window->close();
window = nullptr;
} }
Monitor& WindowSystem::monitor(int index) Monitor* WindowSystem::monitor(int index)
{ {
return p_monitors[index]; return p_monitors[index];
} }
void WindowSystem::destroyMonitor(Monitor* monitor) void WindowSystem::destroyMonitor(Monitor* monitor)
{ {
p_monitors.remove(*monitor); p_monitors.remove(monitor);
} }
} }

View File

@ -10,13 +10,13 @@
namespace hpr::gpu namespace hpr::gpu
{ {
class WindowSystem : WindowContext class WindowSystem : public WindowContext
{ {
protected: protected:
darray<Window> p_windows; darray<Window*> p_windows;
darray<Monitor> p_monitors; darray<Monitor*> p_monitors;
protected: protected:
@ -32,7 +32,7 @@ public:
// Global functions // Global functions
static static
void create(WindowSystem** ws, Provider provider); WindowSystem* create(Provider provider);
static static
void destroy(WindowSystem*& ws); void destroy(WindowSystem*& ws);
@ -40,9 +40,9 @@ public:
// Window interface // Window interface
virtual virtual
void newWindow(Window** window) = 0; Window* newWindow() = 0;
Window& window(int index); Window* window(int index);
void closeWindow(Window* window); void closeWindow(Window* window);
@ -50,10 +50,10 @@ public:
// Monitor interface // Monitor interface
virtual //virtual
void newMonitor(Monitor** monitor) = 0; //void newMonitor(Monitor** monitor) = 0;
Monitor& monitor(int index); Monitor* monitor(int index);
void destroyMonitor(Monitor* monitor); void destroyMonitor(Monitor* monitor);

View File

@ -258,9 +258,11 @@ public:
virtual virtual
int findByAddress(const value_type& value) int findByAddress(const value_type& value)
{ {
for (int n = 0; n < p_size; ++n) // TODO: make better approach
if (std::addressof(*(p_start + n)) == std::addressof(value)) for (int n = 0; n < p_size; ++n) {
if (*std::addressof(*(p_start + n)) == *std::addressof(value))
return n; return n;
}
return -1; return -1;
} }
@ -277,7 +279,7 @@ public:
virtual virtual
void remove(const value_type& value) void remove(const value_type& value)
{ {
size_type index = findByAddress(value); int index = findByAddress(value);
if (index != -1) if (index != -1)
remove(index); remove(index);
else else

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "iterator.hpp" #include "iterator.hpp"
#include <limits> #include <limits>
#include <functional> #include <functional>