1#ifndef LIBSBX_DEVICES_WINDOW_HPP_
2#define LIBSBX_DEVICES_WINDOW_HPP_
9#include <unordered_set>
12#include <libsbx/core/concepts.hpp>
15#include <libsbx/math/vector2.hpp>
17#include <libsbx/signals/signal.hpp>
19#include <libsbx/devices/events.hpp>
20#include <libsbx/devices/input.hpp>
22namespace sbx::devices {
26 std::uint32_t width{};
27 std::uint32_t height{};
35 : _last_mouse_position{-1.0f, -1.0f} {
36 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
39 glfwWindowHint(GLFW_VISIBLE,
false);
42 _title = create_info.title;
43 _width = create_info.width;
44 _height = create_info.height;
46 auto* monitor = glfwGetPrimaryMonitor();
49 throw std::runtime_error{
"Could not get primary monitor"};
52 const auto* video_mode = glfwGetVideoMode(monitor);
54 _width =
static_cast<std::uint32_t
>(video_mode->width);
55 _height =
static_cast<std::uint32_t
>(video_mode->height);
57 _handle = glfwCreateWindow(
static_cast<std::int32_t
>(_width),
static_cast<std::int32_t
>(_height), _title.c_str(),
nullptr,
nullptr);
60 throw std::runtime_error{
"Could not create glfw window"};
63 glfwSetWindowUserPointer(_handle,
this);
65 glfwFocusWindow(_handle);
67 if (glfwRawMouseMotionSupported()) {
68 glfwSetInputMode(_handle, GLFW_RAW_MOUSE_MOTION,
true);
73 glfwSetInputMode(_handle, GLFW_STICKY_KEYS,
true);
75 glfwSetInputMode(_handle, GLFW_LOCK_KEY_MODS,
true);
81 glfwDestroyWindow(_handle);
84 auto handle() -> GLFWwindow* {
88 operator GLFWwindow*() {
92 auto title()
const ->
const std::string& {
96 auto set_title(
const std::string& title) ->
void {
98 glfwSetWindowTitle(_handle, _title.c_str());
101 auto width()
const -> std::uint32_t {
105 auto height()
const -> std::uint32_t {
109 auto aspect_ratio()
const -> std::float_t {
110 return static_cast<std::float_t
>(_width) /
static_cast<std::float_t
>(_height);
118 return glfwWindowShouldClose(_handle);
125 glfwShowWindow(_handle);
132 glfwHideWindow(_handle);
135 auto is_iconified() const noexcept ->
bool {
136 return glfwGetWindowAttrib(_handle, GLFW_ICONIFIED);
139 auto is_focused() const noexcept ->
bool {
140 return glfwGetWindowAttrib(_handle, GLFW_FOCUSED);
143 auto is_visible() const noexcept ->
bool {
144 return glfwGetWindowAttrib(_handle, GLFW_VISIBLE);
147 auto on_window_closed_signal() -> signals::signal<const window_closed_event&>& {
148 return _on_window_closed_signal;
151 auto on_window_moved_signal() -> signals::signal<const window_moved_event&>& {
152 return _on_window_moved_signal;
155 auto on_window_resized_signal() -> signals::signal<const window_resized_event&>& {
156 return _on_window_resized_signal;
159 auto on_framebuffer_resized() -> signals::signal<const framebuffer_resized_event&>& {
160 return _on_framebuffer_resized;
163 auto on_key_pressed() -> signals::signal<const key_pressed_event&>& {
164 return _on_key_pressed;
167 auto on_key_released() -> signals::signal<const key_released_event&>& {
168 return _on_key_released;
171 auto on_mouse_moved() -> signals::signal<const mouse_moved_event&>& {
172 return _on_mouse_moved;
177 void _set_callbacks() {
178 glfwSetWindowUserPointer(_handle,
this);
180 glfwSetWindowCloseCallback(_handle, [](GLFWwindow* window){
181 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
183 self._on_window_closed_signal(window_closed_event{});
186 glfwSetWindowPosCallback(_handle, [](GLFWwindow* window, std::int32_t x, std::int32_t y){
187 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
189 self._on_window_moved_signal(window_moved_event{x, y});
192 glfwSetWindowSizeCallback(_handle, [](GLFWwindow* window, std::int32_t width, std::int32_t height){
193 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
195 self._on_window_resized_signal(window_resized_event{width, height});
198 glfwSetFramebufferSizeCallback(_handle, [](GLFWwindow* window, std::int32_t width, std::int32_t height){
199 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
201 self._on_framebuffer_resized(framebuffer_resized_event{width, height});
203 self._width =
static_cast<std::uint32_t
>(width);
204 self._height =
static_cast<std::uint32_t
>(height);
207 glfwSetKeyCallback(_handle, [](GLFWwindow* window, std::int32_t key, [[maybe_unused]] std::int32_t scancode, std::int32_t action, std::int32_t mods){
208 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
210 if (action == GLFW_PRESS) {
211 input::_update_key_state(
static_cast<devices::key
>(key), input_action::press);
212 self._on_key_pressed(key_pressed_event{
static_cast<devices::key
>(key),
static_cast<devices::input_mod
>(mods)});
213 }
else if (action == GLFW_RELEASE) {
214 input::_update_key_state(
static_cast<devices::key
>(key), input_action::release);
215 self._on_key_released(key_released_event{
static_cast<devices::key
>(key),
static_cast<devices::input_mod
>(mods)});
219 glfwSetCursorPosCallback(_handle, [](
auto* window,
auto x,
auto y){
220 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
222 auto mouse_position = math::vector2{
static_cast<std::float_t
>(x),
static_cast<std::float_t
>(y)};
224 if (self._last_mouse_position.x() < 0.0f || self._last_mouse_position.y() < 0.0f) {
225 self._on_mouse_moved(mouse_moved_event{mouse_position.x(), mouse_position.y()});
227 self._on_mouse_moved(mouse_moved_event{mouse_position.x() - self._last_mouse_position.x(), mouse_position.y() - self._last_mouse_position.y()});
228 self._last_mouse_position = mouse_position;
231 input::_update_mouse_position(mouse_position);
234 glfwSetMouseButtonCallback(_handle, [](
auto* window,
auto button,
auto action,
auto mods){
235 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
237 if (action == GLFW_PRESS) {
238 input::_update_mouse_button_state(
static_cast<devices::mouse_button
>(button), input_action::press);
239 self._on_mouse_button_pressed(mouse_button_pressed_event{
static_cast<devices::mouse_button
>(button),
static_cast<devices::input_mod
>(mods)});
240 }
else if (action == GLFW_RELEASE) {
241 input::_update_mouse_button_state(
static_cast<devices::mouse_button
>(button), input_action::release);
242 self._on_mouse_button_released(mouse_button_released_event{
static_cast<devices::mouse_button
>(button),
static_cast<devices::input_mod
>(mods)});
246 glfwSetScrollCallback(_handle, [](
auto* window,
auto x,
auto y){
247 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
249 self._on_mouse_scrolled(mouse_scrolled_event{
static_cast<std::float_t
>(x),
static_cast<std::float_t
>(y)});
251 input::_update_scroll_delta(math::vector2{
static_cast<std::float_t
>(x),
static_cast<std::float_t
>(y)});
255 std::string _title{};
256 std::uint32_t _width{};
257 std::uint32_t _height{};
259 GLFWwindow* _handle{};
261 math::vector2 _last_mouse_position;
263 signals::signal<const window_closed_event&> _on_window_closed_signal;
264 signals::signal<const window_moved_event&> _on_window_moved_signal;
265 signals::signal<const window_resized_event&> _on_window_resized_signal;
266 signals::signal<const framebuffer_resized_event&> _on_framebuffer_resized;
267 signals::signal<const key_pressed_event&> _on_key_pressed;
268 signals::signal<const key_released_event&> _on_key_released;
269 signals::signal<const mouse_moved_event&> _on_mouse_moved;
270 signals::signal<const mouse_button_pressed_event&> _on_mouse_button_pressed;
271 signals::signal<const mouse_button_released_event&> _on_mouse_button_released;
272 signals::signal<const mouse_scrolled_event&> _on_mouse_scrolled;
Definition: window.hpp:30
auto show() -> void
Makes the window visible.
Definition: window.hpp:124
auto should_close() -> bool
Determins if the window should be closed.
Definition: window.hpp:117
auto hide() -> void
Hides the window.
Definition: window.hpp:131
Definition: window.hpp:24