Files
rogue/source/ui/display.cpp

135 lines
4.4 KiB
C++

#include "display.hpp"
#include <stdexcept>
#include <utility>
namespace rog::ui {
GLFWwindow *display::create_window(glm::uvec2 extent, std::string_view title,
void *user_data) {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
const auto window =
glfwCreateWindow(extent.x, extent.y, title.data(), nullptr, nullptr);
if (window == nullptr) {
auto description = static_cast<const char *>(nullptr);
glfwGetError(&description);
throw std::runtime_error(description);
}
glfwSetWindowUserPointer(window, user_data);
return window;
}
display::display(user_input *input, glm::uvec2 extent, std::string_view title)
: handle(create_window(extent, title, this)), title(title), input(input) {
glfwSetWindowSizeCallback(
handle, [](GLFWwindow *window, int width, int height) {
auto self = static_cast<display *>(glfwGetWindowUserPointer(window));
for (const auto &cb : self->resize_callbacks) {
cb(glm::uvec2(width, height));
}
});
glfwSetKeyCallback(handle, [](GLFWwindow *window, int key,
[[maybe_unused]] int scancode, int action,
[[maybe_unused]] int mods) {
auto self = static_cast<display *>(glfwGetWindowUserPointer(window));
if (action == GLFW_RELEASE) {
self->input->set_key_state(static_cast<key_code>(key),
key_state::released);
} else if (action == GLFW_REPEAT) {
self->input->set_key_state(static_cast<key_code>(key), key_state::repeat);
} else if (action == GLFW_PRESS) {
self->input->set_key_state(static_cast<key_code>(key),
key_state::pressed);
}
});
glfwSetCursorPosCallback(handle, [](GLFWwindow *window, double x, double y) {
static_cast<display *>(glfwGetWindowUserPointer(window))
->input->set_mouse_pos(glm::vec2{x, y});
});
glfwSetMouseButtonCallback(
handle, [](GLFWwindow *window, int button, int action, int mods) {
auto self = static_cast<display *>(glfwGetWindowUserPointer(window));
auto mouse_button = ui::mouse_button::left;
switch (button) {
case GLFW_MOUSE_BUTTON_LEFT:
mouse_button = ui::mouse_button::left;
break;
case GLFW_MOUSE_BUTTON_RIGHT:
mouse_button = ui::mouse_button::right;
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
mouse_button = ui::mouse_button::middle;
break;
default:;
}
auto mouse_action = ui::button_state::down;
switch (action) {
case GLFW_PRESS:
mouse_action = ui::button_state::down;
break;
case GLFW_RELEASE:
mouse_action = ui::button_state::up;
break;
default:;
}
self->input->set_mouse_button(mouse_button, mouse_action);
});
}
display::~display() { glfwDestroyWindow(handle); }
display::display(const display &rhs)
: handle(create_window(rhs.extent(), rhs.title, this)), title(rhs.title) {
glfwSetWindowSizeCallback(
handle, [](GLFWwindow *window, int width, int height) {
auto self = static_cast<display *>(glfwGetWindowUserPointer(window));
for (const auto &cb : self->resize_callbacks) {
cb(glm::uvec2(width, height));
}
});
}
display::display(display &&rhs) noexcept
: handle(std::exchange(rhs.handle, nullptr)), title(rhs.title) {}
display &display::operator=(const display &rhs) { return *this = display(rhs); }
display &display::operator=(display &&rhs) noexcept {
std::swap(handle, rhs.handle);
std::swap(title, rhs.title);
return *this;
}
bool display::should_close() const noexcept {
return glfwWindowShouldClose(handle);
}
glm::uvec2 display::extent() const noexcept {
auto extent = glm::ivec2();
glfwGetFramebufferSize(handle, &extent.x, &extent.y);
return extent;
}
void display::poll_events() { glfwPollEvents(); }
vk::raii::SurfaceKHR
display::create_surface(const vk::raii::Instance &instance) {
auto c_surface = VkSurfaceKHR();
glfwCreateWindowSurface(*instance, handle, nullptr, &c_surface);
return vk::raii::SurfaceKHR(instance, c_surface);
}
void display::resize_callback(std::function<void(glm::uvec2 extent)> callback) {
resize_callbacks.push_back(callback);
}
GLFWwindow *display::raw() const noexcept { return handle; }
void display::request_close() noexcept {
glfwSetWindowShouldClose(handle, true);
}
} // namespace rog::ui