#include "glfw.hpp" #include "event/type.hpp" #include "event/api.hpp" namespace VE { glfw::glfw() { if (!glfwInit()) { hack::error()("Not glfw window init"); std::terminate(); } } glfw::~glfw() { hack::warn(": ")("Destroy glfw window", m_win_data.m_name); glfwDestroyWindow(m_win); glfwTerminate(); } void glfw::init(std::string win_name) { m_win_data.m_name = win_name; set_hint(); set_window(); set_graphic_context(); set_pointer(); set_key_callback(); set_mouse_callback(); set_window_callback(); set_opengl(); } void glfw::set_hint() { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_SAMPLES, 4); hack::log()("Set glfw window hint"); } void glfw::set_window() { // два последних nullptr // первый - устанавливает монитор на котром будет открытие(основной, дополнительнй) // второй - делиться ли ресурсами с кем-то m_win = glfwCreateWindow( glfwGetVideoMode(glfwGetPrimaryMonitor())->width, glfwGetVideoMode(glfwGetPrimaryMonitor())->height, m_win_data.m_name.c_str(), nullptr, nullptr ); if(m_win == NULL) { hack::error()("Failed to create GLFW window"); glfwTerminate(); std::terminate(); } glfwGetWindowSize(m_win, &m_win_data.m_width, &m_win_data.m_height); hack::log(": ")("Created glfw window", m_win_data.m_name); hack::log(" = ")(" width", m_win_data.m_width); hack::log(" = ")(" height", m_win_data.m_height); } void glfw::set_graphic_context() { m_context = std::make_unique(m_win); hack::log()("Set context"); } void glfw::set_pointer() { glfwSetWindowUserPointer(m_win, &m_win_data); } GLFWwindow* glfw::get_win() const { return m_win; } int glfw::width() const { return m_win_data.m_width; } int glfw::height() const { return m_win_data.m_height; } void glfw::update() { glfwPollEvents(); m_context->swap_buffers(); } void glfw::clear() const { glClearColor(m_bgcolor.r, m_bgcolor.g, m_bgcolor.b, m_bgcolor.a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void glfw::set_key_callback() { glfwSetKeyCallback(m_win, [](GLFWwindow* w, int key, int scancode, int action, int mods) { // HERE // тут одноврекменно срабатывает только один сигнал // т.е. если нажада клавиша и удерживается сигнал о повторе идет // но если нажать одновременно еще, то сигнал о той нажатой пропадает // нужносамому реализовывать функцию повтора а не полагаться на внутреннюю // реализацию glfw switch (action) { case GLFW_PRESS: { VE::EMIT(event_type::KEY_PRESSED, key); break; } case GLFW_RELEASE: { VE::EMIT(event_type::KEY_RELEASED, key); break; } case GLFW_REPEAT: { VE::EMIT(event_type::KEY_REPEATE, key); break; } } }); } void glfw::set_mouse_callback() { glfwSetMouseButtonCallback(m_win, [](GLFWwindow* w, int button, int action, int mods) { switch (action) { case GLFW_PRESS: { static auto time = std::chrono::high_resolution_clock::now(); auto local = std::chrono::high_resolution_clock::now(); std::chrono::duration duration = local - time; if (duration.count() > 10 && duration.count() < 200) VE::EMIT(event_type::MOUSE_BUTTON_DOUBLE_PRESSED, button); else VE::EMIT(event_type::MOUSE_BUTTON_PRESSED, button); time = local; break; } case GLFW_RELEASE: { VE::EMIT(event_type::MOUSE_BUTTON_RELEASED, button); break; } } }); glfwSetScrollCallback(m_win, [](GLFWwindow* w, double xOffset, double yOffset) { try { auto data = std::pair{ static_cast(xOffset), static_cast(yOffset) }; VE::EMIT(event_type::MOUSE_SCROLL, data); } catch(std::exception& e) { hack::log()("VE_ERROR: ", e.what()); } }); glfwSetCursorPosCallback(m_win, [](GLFWwindow* w, double xPos, double yPos) { try { auto data = std::pair{ static_cast(xPos), static_cast(yPos) }; VE::EMIT(event_type::MOUSE_CURSOR_POSITION, data); } catch(std::exception& e) { hack::log()("VE_ERROR: ", e.what()); } }); } void glfw::set_window_callback() { glfwSetWindowSizeLimits(m_win, m_win_data.m_width, m_win_data.m_height, GLFW_DONT_CARE, GLFW_DONT_CARE); glfwSetWindowSizeCallback(m_win, [](GLFWwindow* w, int width, int height) { auto d = static_cast(glfwGetWindowUserPointer(w)); d->m_width = width; d->m_height = height; try { auto data = std::pair{ static_cast(width), static_cast(height) }; VE::EMIT(event_type::WINDOW_RESIZE, data); } catch(std::exception& e) { hack::log()("VE_ERROR: ", e.what()); } }); glfwSetWindowCloseCallback(m_win, [](GLFWwindow* w) { try { VE::EMIT(event_type::WINDOW_CLOSE, nullptr); } catch(std::exception& e) { hack::log()("VE_ERROR: ", e.what()); } }); glfwSetWindowFocusCallback(m_win, [](GLFWwindow* w, int focused) { try { VE::EMIT(event_type::WINDOW_FOCUS, focused); } catch(std::exception& e) { hack::log()("VE_ERROR: ", e.what()); } }); } void glfw::set_opengl() { glEnable(GL_DEPTH_TEST); glClearColor(0.07f, 0.13f, 0.17f, 1.0f); glViewport(0, 0, m_win_data.m_width, m_win_data.m_height); } }