1#ifndef LIBSBX_DEVICES_WINDOW_HPP_
2#define LIBSBX_DEVICES_WINDOW_HPP_
9#include <unordered_set>
12#include <libsbx/utility/target.hpp>
14#include <libsbx/core/concepts.hpp>
16#include <libsbx/core/version.hpp>
18#include <libsbx/math/vector2.hpp>
20#include <libsbx/signals/signal.hpp>
22#include <libsbx/devices/events.hpp>
23#include <libsbx/devices/input.hpp>
25namespace sbx::devices {
29 std::uint32_t width{};
30 std::uint32_t height{};
38 : _last_mouse_position{-1.0f, -1.0f} {
39 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
42 glfwWindowHint(GLFW_VISIBLE,
false);
45 _width = create_info.width;
46 _height = create_info.height;
48 if (utility::build_configuration_v == utility::build_configuration::debug) {
49 _title = fmt::format(
"{} [Debug] v" SBX_CORE_VERSION_STRING
"+" SBX_COMPILE_TIMESTAMP, create_info.title);
52 auto* monitor = glfwGetPrimaryMonitor();
55 throw std::runtime_error{
"Could not get primary monitor"};
58 const auto* video_mode = glfwGetVideoMode(monitor);
60 _width =
static_cast<std::uint32_t
>(video_mode->width);
61 _height =
static_cast<std::uint32_t
>(video_mode->height);
63 glfwWindowHint(GLFW_RED_BITS, video_mode->redBits);
64 glfwWindowHint(GLFW_GREEN_BITS, video_mode->greenBits);
65 glfwWindowHint(GLFW_BLUE_BITS, video_mode->blueBits);
66 glfwWindowHint(GLFW_REFRESH_RATE, video_mode->refreshRate);
68 _handle = glfwCreateWindow(
static_cast<std::int32_t
>(_width),
static_cast<std::int32_t
>(_height), _title.c_str(),
nullptr,
nullptr);
71 throw std::runtime_error{
"Could not create glfw window"};
74 glfwSetWindowUserPointer(_handle,
this);
76 glfwFocusWindow(_handle);
78 if (glfwRawMouseMotionSupported()) {
79 glfwSetInputMode(_handle, GLFW_RAW_MOUSE_MOTION,
true);
84 glfwSetInputMode(_handle, GLFW_STICKY_KEYS,
true);
86 glfwSetInputMode(_handle, GLFW_LOCK_KEY_MODS,
true);
92 glfwDestroyWindow(_handle);
95 auto handle() -> GLFWwindow* {
99 operator GLFWwindow*() {
103 auto title()
const ->
const std::string& {
107 auto set_title(
const std::string& title) ->
void {
110 if (utility::build_configuration_v == utility::build_configuration::debug) {
111 _title = fmt::format(
"{} [Debug] v" SBX_CORE_VERSION_STRING
"+" SBX_COMPILE_TIMESTAMP, _title);
114 glfwSetWindowTitle(_handle, _title.c_str());
117 auto width()
const -> std::uint32_t {
121 auto height()
const -> std::uint32_t {
125 auto aspect_ratio()
const -> std::float_t {
126 return static_cast<std::float_t
>(_width) /
static_cast<std::float_t
>(_height);
134 return glfwWindowShouldClose(_handle);
141 glfwShowWindow(_handle);
148 glfwHideWindow(_handle);
151 auto is_iconified() const noexcept ->
bool {
152 return glfwGetWindowAttrib(_handle, GLFW_ICONIFIED);
155 auto is_focused() const noexcept ->
bool {
156 return glfwGetWindowAttrib(_handle, GLFW_FOCUSED);
159 auto is_visible() const noexcept ->
bool {
160 return glfwGetWindowAttrib(_handle, GLFW_VISIBLE);
163 auto on_window_closed_signal() -> signals::signal<const window_closed_event&>& {
164 return _on_window_closed_signal;
167 auto on_window_moved_signal() -> signals::signal<const window_moved_event&>& {
168 return _on_window_moved_signal;
171 auto on_window_resized_signal() -> signals::signal<const window_resized_event&>& {
172 return _on_window_resized_signal;
175 auto on_framebuffer_resized() -> signals::signal<const framebuffer_resized_event&>& {
176 return _on_framebuffer_resized;
179 auto on_key_pressed() -> signals::signal<const key_pressed_event&>& {
180 return _on_key_pressed;
183 auto on_key_released() -> signals::signal<const key_released_event&>& {
184 return _on_key_released;
187 auto on_mouse_moved() -> signals::signal<const mouse_moved_event&>& {
188 return _on_mouse_moved;
193 void _set_callbacks() {
194 glfwSetWindowUserPointer(_handle,
this);
196 glfwSetWindowCloseCallback(_handle, [](GLFWwindow* window){
197 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
199 self._on_window_closed_signal(window_closed_event{});
202 glfwSetWindowPosCallback(_handle, [](GLFWwindow* window, std::int32_t x, std::int32_t y){
203 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
205 self._on_window_moved_signal(window_moved_event{x, y});
208 glfwSetWindowSizeCallback(_handle, [](GLFWwindow* window, std::int32_t width, std::int32_t height){
209 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
211 self._on_window_resized_signal(window_resized_event{width, height});
214 glfwSetFramebufferSizeCallback(_handle, [](GLFWwindow* window, std::int32_t width, std::int32_t height){
215 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
217 self._on_framebuffer_resized(framebuffer_resized_event{width, height});
219 self._width =
static_cast<std::uint32_t
>(width);
220 self._height =
static_cast<std::uint32_t
>(height);
223 glfwSetKeyCallback(_handle, [](GLFWwindow* window, std::int32_t key, [[maybe_unused]] std::int32_t scancode, std::int32_t action, std::int32_t mods){
224 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
226 if (action == GLFW_PRESS) {
227 input::_update_key_state(
static_cast<devices::key
>(key), input_action::press);
228 self._on_key_pressed(key_pressed_event{
static_cast<devices::key
>(key),
static_cast<devices::input_mod
>(mods)});
229 }
else if (action == GLFW_RELEASE) {
230 input::_update_key_state(
static_cast<devices::key
>(key), input_action::release);
231 self._on_key_released(key_released_event{
static_cast<devices::key
>(key),
static_cast<devices::input_mod
>(mods)});
235 glfwSetCursorPosCallback(_handle, [](
auto* window,
auto x,
auto y){
236 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
238 auto mouse_position = math::vector2{
static_cast<std::float_t
>(x),
static_cast<std::float_t
>(y)};
240 if (self._last_mouse_position.x() < 0.0f || self._last_mouse_position.y() < 0.0f) {
241 self._on_mouse_moved(mouse_moved_event{mouse_position.x(), mouse_position.y()});
243 self._on_mouse_moved(mouse_moved_event{mouse_position.x() - self._last_mouse_position.x(), mouse_position.y() - self._last_mouse_position.y()});
244 self._last_mouse_position = mouse_position;
247 input::_update_mouse_position(mouse_position);
250 glfwSetMouseButtonCallback(_handle, [](
auto* window,
auto button,
auto action,
auto mods){
251 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
253 if (action == GLFW_PRESS) {
254 input::_update_mouse_button_state(
static_cast<devices::mouse_button
>(button), input_action::press);
255 self._on_mouse_button_pressed(mouse_button_pressed_event{
static_cast<devices::mouse_button
>(button),
static_cast<devices::input_mod
>(mods)});
256 }
else if (action == GLFW_RELEASE) {
257 input::_update_mouse_button_state(
static_cast<devices::mouse_button
>(button), input_action::release);
258 self._on_mouse_button_released(mouse_button_released_event{
static_cast<devices::mouse_button
>(button),
static_cast<devices::input_mod
>(mods)});
262 glfwSetScrollCallback(_handle, [](
auto* window,
auto x,
auto y){
263 auto& self = *
static_cast<devices::window*
>(glfwGetWindowUserPointer(window));
265 self._on_mouse_scrolled(mouse_scrolled_event{
static_cast<std::float_t
>(x),
static_cast<std::float_t
>(y)});
267 input::_update_scroll_delta(math::vector2{
static_cast<std::float_t
>(x),
static_cast<std::float_t
>(y)});
271 std::string _title{};
272 std::uint32_t _width{};
273 std::uint32_t _height{};
275 GLFWwindow* _handle{};
277 math::vector2 _last_mouse_position;
279 signals::signal<const window_closed_event&> _on_window_closed_signal;
280 signals::signal<const window_moved_event&> _on_window_moved_signal;
281 signals::signal<const window_resized_event&> _on_window_resized_signal;
282 signals::signal<const framebuffer_resized_event&> _on_framebuffer_resized;
283 signals::signal<const key_pressed_event&> _on_key_pressed;
284 signals::signal<const key_released_event&> _on_key_released;
285 signals::signal<const mouse_moved_event&> _on_mouse_moved;
286 signals::signal<const mouse_button_pressed_event&> _on_mouse_button_pressed;
287 signals::signal<const mouse_button_released_event&> _on_mouse_button_released;
288 signals::signal<const mouse_scrolled_event&> _on_mouse_scrolled;
Definition: window.hpp:33
auto show() -> void
Makes the window visible.
Definition: window.hpp:140
auto should_close() -> bool
Determins if the window should be closed.
Definition: window.hpp:133
auto hide() -> void
Hides the window.
Definition: window.hpp:147
Definition: window.hpp:27