2025-07-05 13:28:41 +03:30
|
|
|
#include <GLFW/glfw3.h>
|
|
|
|
#include <engine/events/char.hpp>
|
|
|
|
#include <engine/events/event.hpp>
|
|
|
|
#include <engine/events/keyboard.hpp>
|
|
|
|
#include <engine/events/mouse.hpp>
|
|
|
|
#include <engine/events/window.hpp>
|
|
|
|
#include <engine/graphics/graphics_context.hpp>
|
|
|
|
#include <engine/platform/os/linux/l_window.hpp>
|
|
|
|
|
|
|
|
namespace Light {
|
|
|
|
|
2025-07-06 14:02:50 +03:30
|
|
|
auto Window::create(std::function<void(Event &)> callback) -> Scope<Window>
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 15:36:53 +03:30
|
|
|
return create_scope<lWindow>(callback);
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
lWindow::lWindow(std::function<void(Event &)> callback)
|
2025-07-05 14:23:01 +03:30
|
|
|
: m_handle(nullptr)
|
|
|
|
, m_event_callback(callback)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
|
|
|
// init glfw
|
2025-07-05 15:36:53 +03:30
|
|
|
lt_assert(glfwInit(), "lWindow::lWindow: failed to initialize 'glfw'");
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
// create window
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
|
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
|
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
m_handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr);
|
2025-07-05 15:36:53 +03:30
|
|
|
lt_assert(m_handle, "lWindow::lWindow: failed to create 'GLFWwindow'");
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
// bind event stuff
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowUserPointer(m_handle, &m_event_callback);
|
2025-07-05 15:36:53 +03:30
|
|
|
bind_glfw_events();
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
// create graphics context
|
2025-07-05 15:36:53 +03:30
|
|
|
m_graphics_context = GraphicsContext::create(GraphicsAPI::OpenGL, m_handle);
|
|
|
|
lt_assert(m_graphics_context, "lWindow::lWindow: failed to create 'GraphicsContext'");
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
lWindow::~lWindow()
|
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwDestroyWindow(m_handle);
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::poll_events()
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
|
|
|
glfwPollEvents();
|
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::on_event(const Event &event)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 15:36:53 +03:30
|
|
|
switch (event.get_event_type())
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
|
|
|
/* closed */
|
|
|
|
case EventType::WindowClosed: b_Closed = true; break;
|
|
|
|
|
|
|
|
/* resized */
|
2025-07-05 15:36:53 +03:30
|
|
|
case EventType::WindowResized: on_window_resize((const WindowResizedEvent &)event); break;
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::on_window_resize(const WindowResizedEvent &event)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 15:36:53 +03:30
|
|
|
m_properties.size = event.get_size();
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
void lWindow::
|
2025-07-05 15:36:53 +03:30
|
|
|
set_properties(const WindowProperties &properties, bool overrideVisibility /* = false */)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
|
|
|
// save the visibility status and re-assign if 'overrideVisibility' is false
|
2025-07-06 14:02:50 +03:30
|
|
|
auto visible = overrideVisibility ? properties.visible : m_properties.visible;
|
2025-07-05 14:23:01 +03:30
|
|
|
m_properties = properties;
|
|
|
|
m_properties.visible = visible;
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
// set properties
|
2025-07-05 15:36:53 +03:30
|
|
|
set_title(properties.title);
|
|
|
|
set_size(properties.size);
|
|
|
|
set_v_sync(properties.vsync);
|
|
|
|
set_visibility(visible);
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::set_title(const std::string &title)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
m_properties.title = title;
|
2025-07-05 13:28:41 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowTitle(m_handle, title.c_str());
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::set_size(const glm::uvec2 &size, bool additive /* = false */)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
m_properties.size.x = size.x == 0u ? m_properties.size.x :
|
|
|
|
additive ? m_properties.size.x + size.x :
|
2025-07-05 13:28:41 +03:30
|
|
|
size.x;
|
2025-07-05 14:23:01 +03:30
|
|
|
m_properties.size.y = size.y == 0u ? m_properties.size.y :
|
|
|
|
additive ? m_properties.size.y + size.y :
|
2025-07-05 13:28:41 +03:30
|
|
|
size.y;
|
|
|
|
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowSize(m_handle, size.x, size.y);
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::set_v_sync(bool vsync, bool toggle /* = false */)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
m_properties.vsync = toggle ? !m_properties.vsync : vsync;
|
2025-07-05 13:28:41 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSwapInterval(m_properties.vsync);
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::set_visibility(bool visible, bool toggle)
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
m_properties.visible = toggle ? !m_properties.visible : visible;
|
2025-07-05 13:28:41 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
if (m_properties.visible)
|
|
|
|
glfwShowWindow(m_handle);
|
2025-07-05 13:28:41 +03:30
|
|
|
else
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwHideWindow(m_handle);
|
2025-07-05 13:28:41 +03:30
|
|
|
}
|
|
|
|
|
2025-07-05 15:36:53 +03:30
|
|
|
void lWindow::bind_glfw_events()
|
2025-07-05 13:28:41 +03:30
|
|
|
{
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetCursorPosCallback(m_handle, [](GLFWwindow *window, double xpos, double ypos) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
2025-07-05 13:28:41 +03:30
|
|
|
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = MouseMovedEvent {
|
|
|
|
static_cast<float>(xpos),
|
|
|
|
static_cast<float>(ypos),
|
|
|
|
};
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
});
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetMouseButtonCallback(m_handle, [](GLFWwindow *window, int button, int action, int mods) {
|
2025-07-05 13:28:41 +03:30
|
|
|
std::function<void(Event &)> callback = *(std::function<void(Event &)> *)
|
|
|
|
glfwGetWindowUserPointer(window);
|
|
|
|
|
|
|
|
if (action == GLFW_PRESS)
|
|
|
|
{
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = ButtonPressedEvent { button };
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
}
|
|
|
|
else if (action == GLFW_RELEASE)
|
|
|
|
{
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = ButtonReleasedEvent { button };
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetScrollCallback(m_handle, [](GLFWwindow *window, double xoffset, double yoffset) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
2025-07-05 13:28:41 +03:30
|
|
|
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = WheelScrolledEvent { static_cast<float>(yoffset) };
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
});
|
|
|
|
|
|
|
|
glfwSetKeyCallback(
|
2025-07-05 14:23:01 +03:30
|
|
|
m_handle,
|
2025-07-05 13:28:41 +03:30
|
|
|
[](GLFWwindow *window, int key, int scancode, int action, int mods) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
if (action == GLFW_PRESS)
|
|
|
|
{
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = KeyPressedEvent { key };
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
}
|
|
|
|
else if (action == GLFW_RELEASE)
|
|
|
|
{
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = KeyReleasedEvent { key };
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2025-07-06 14:02:50 +03:30
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetCharCallback(m_handle, [](GLFWwindow *window, unsigned int character) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
2025-07-05 13:28:41 +03:30
|
|
|
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = SetCharEvent { character };
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
});
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowPosCallback(m_handle, [](GLFWwindow *window, int xpos, int ypos) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
|
|
|
auto event = WindowMovedEvent { xpos, ypos };
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
callback(event);
|
|
|
|
});
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowSizeCallback(m_handle, [](GLFWwindow *window, int width, int height) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
|
|
|
auto event = WindowResizedEvent {
|
|
|
|
static_cast<unsigned int>(width),
|
|
|
|
static_cast<unsigned int>(height),
|
|
|
|
};
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
callback(event);
|
|
|
|
});
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowCloseCallback(m_handle, [](GLFWwindow *window) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
|
|
|
auto event = WindowClosedEvent {};
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
callback(event);
|
|
|
|
});
|
|
|
|
|
2025-07-05 14:23:01 +03:30
|
|
|
glfwSetWindowFocusCallback(m_handle, [](GLFWwindow *window, int focus) {
|
2025-07-06 14:02:50 +03:30
|
|
|
auto callback = *(std::function<void(Event &)> *)glfwGetWindowUserPointer(window);
|
2025-07-05 13:28:41 +03:30
|
|
|
|
|
|
|
if (focus == GLFW_TRUE)
|
|
|
|
{
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = WindowGainFocusEvent {};
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-07-06 14:02:50 +03:30
|
|
|
auto event = WindowLostFocusEvent {};
|
2025-07-05 13:28:41 +03:30
|
|
|
callback(event);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Light
|