Project Alice
Loading...
Searching...
No Matches
window_nix.cpp
Go to the documentation of this file.
1#include "window.hpp"
2#include "map.hpp"
3
4#include <GLFW/glfw3.h>
5#include <unordered_map>
6
7namespace window {
8
9static const std::unordered_map<int, sys::virtual_key> glfw_key_to_virtual_key = {{GLFW_KEY_UNKNOWN, sys::virtual_key::NONE},
10 {GLFW_KEY_SPACE, sys::virtual_key::SPACE}, {GLFW_KEY_APOSTROPHE, sys::virtual_key::QUOTE},
11 {GLFW_KEY_COMMA, sys::virtual_key::COMMA}, {GLFW_KEY_EQUAL, sys::virtual_key::PLUS},
12 {GLFW_KEY_MINUS, sys::virtual_key::MINUS}, {GLFW_KEY_PERIOD, sys::virtual_key::PERIOD},
13 {GLFW_KEY_SLASH, sys::virtual_key::FORWARD_SLASH}, {GLFW_KEY_0, sys::virtual_key::NUM_0},
14 {GLFW_KEY_1, sys::virtual_key::NUM_1}, {GLFW_KEY_2, sys::virtual_key::NUM_2}, {GLFW_KEY_3, sys::virtual_key::NUM_3},
15 {GLFW_KEY_4, sys::virtual_key::NUM_4}, {GLFW_KEY_5, sys::virtual_key::NUM_5}, {GLFW_KEY_6, sys::virtual_key::NUM_6},
16 {GLFW_KEY_7, sys::virtual_key::NUM_7}, {GLFW_KEY_8, sys::virtual_key::NUM_8}, {GLFW_KEY_9, sys::virtual_key::NUM_9},
17 {GLFW_KEY_SEMICOLON, sys::virtual_key::SEMICOLON}, {GLFW_KEY_EQUAL, sys::virtual_key::OEM_NEC_EQUAL},
18 {GLFW_KEY_A, sys::virtual_key::A}, {GLFW_KEY_B, sys::virtual_key::B}, {GLFW_KEY_C, sys::virtual_key::C},
19 {GLFW_KEY_D, sys::virtual_key::D}, {GLFW_KEY_E, sys::virtual_key::E}, {GLFW_KEY_F, sys::virtual_key::F},
20 {GLFW_KEY_G, sys::virtual_key::G}, {GLFW_KEY_H, sys::virtual_key::H}, {GLFW_KEY_I, sys::virtual_key::I},
21 {GLFW_KEY_J, sys::virtual_key::J}, {GLFW_KEY_K, sys::virtual_key::K}, {GLFW_KEY_L, sys::virtual_key::L},
22 {GLFW_KEY_M, sys::virtual_key::M}, {GLFW_KEY_N, sys::virtual_key::N}, {GLFW_KEY_O, sys::virtual_key::O},
23 {GLFW_KEY_P, sys::virtual_key::P}, {GLFW_KEY_Q, sys::virtual_key::Q}, {GLFW_KEY_R, sys::virtual_key::R},
24 {GLFW_KEY_S, sys::virtual_key::S}, {GLFW_KEY_T, sys::virtual_key::T}, {GLFW_KEY_U, sys::virtual_key::U},
25 {GLFW_KEY_V, sys::virtual_key::V}, {GLFW_KEY_W, sys::virtual_key::W}, {GLFW_KEY_X, sys::virtual_key::X},
26 {GLFW_KEY_Y, sys::virtual_key::Y}, {GLFW_KEY_Z, sys::virtual_key::Z}, {GLFW_KEY_LEFT_BRACKET, sys::virtual_key::OPEN_BRACKET},
27 {GLFW_KEY_BACKSLASH, sys::virtual_key::BACK_SLASH}, {GLFW_KEY_RIGHT_BRACKET, sys::virtual_key::CLOSED_BRACKET},
28 {GLFW_KEY_GRAVE_ACCENT, sys::virtual_key::TILDA}, {GLFW_KEY_WORLD_1, sys::virtual_key::NONE},
29 {GLFW_KEY_WORLD_2, sys::virtual_key::NONE}, {GLFW_KEY_ESCAPE, sys::virtual_key::ESCAPE},
30 {GLFW_KEY_ENTER, sys::virtual_key::RETURN}, {GLFW_KEY_TAB, sys::virtual_key::TAB},
31 {GLFW_KEY_BACKSPACE, sys::virtual_key::BACK}, {GLFW_KEY_INSERT, sys::virtual_key::INSERT},
32 {GLFW_KEY_DELETE, sys::virtual_key::DELETE_KEY}, {GLFW_KEY_RIGHT, sys::virtual_key::RIGHT},
33 {GLFW_KEY_LEFT, sys::virtual_key::LEFT}, {GLFW_KEY_DOWN, sys::virtual_key::DOWN}, {GLFW_KEY_UP, sys::virtual_key::UP},
34 {GLFW_KEY_PAGE_UP, sys::virtual_key::PRIOR}, {GLFW_KEY_PAGE_DOWN, sys::virtual_key::NEXT},
35 {GLFW_KEY_HOME, sys::virtual_key::HOME}, {GLFW_KEY_END, sys::virtual_key::END},
36 {GLFW_KEY_CAPS_LOCK, sys::virtual_key::CAPITAL}, {GLFW_KEY_SCROLL_LOCK, sys::virtual_key::SCROLL},
37 {GLFW_KEY_NUM_LOCK, sys::virtual_key::NUMLOCK}, {GLFW_KEY_PRINT_SCREEN, sys::virtual_key::PRINT},
38 {GLFW_KEY_PAUSE, sys::virtual_key::PAUSE}, {GLFW_KEY_F1, sys::virtual_key::F1}, {GLFW_KEY_F2, sys::virtual_key::F2},
39 {GLFW_KEY_F3, sys::virtual_key::F3}, {GLFW_KEY_F4, sys::virtual_key::F4}, {GLFW_KEY_F5, sys::virtual_key::F5},
40 {GLFW_KEY_F6, sys::virtual_key::F6}, {GLFW_KEY_F7, sys::virtual_key::F7}, {GLFW_KEY_F8, sys::virtual_key::F8},
41 {GLFW_KEY_F9, sys::virtual_key::F9}, {GLFW_KEY_F10, sys::virtual_key::F10}, {GLFW_KEY_F11, sys::virtual_key::F11},
42 {GLFW_KEY_F12, sys::virtual_key::F12}, {GLFW_KEY_F13, sys::virtual_key::F13}, {GLFW_KEY_F14, sys::virtual_key::F14},
43 {GLFW_KEY_F15, sys::virtual_key::F15}, {GLFW_KEY_F16, sys::virtual_key::F16}, {GLFW_KEY_F17, sys::virtual_key::F17},
44 {GLFW_KEY_F18, sys::virtual_key::F18}, {GLFW_KEY_F19, sys::virtual_key::F19}, {GLFW_KEY_F20, sys::virtual_key::F20},
45 {GLFW_KEY_F21, sys::virtual_key::F21}, {GLFW_KEY_F22, sys::virtual_key::F22}, {GLFW_KEY_F23, sys::virtual_key::F23},
46 {GLFW_KEY_F24, sys::virtual_key::F24}, {GLFW_KEY_F25, sys::virtual_key::NONE}, {GLFW_KEY_KP_0, sys::virtual_key::NUMPAD0},
47 {GLFW_KEY_KP_1, sys::virtual_key::NUMPAD1}, {GLFW_KEY_KP_2, sys::virtual_key::NUMPAD2},
48 {GLFW_KEY_KP_3, sys::virtual_key::NUMPAD3}, {GLFW_KEY_KP_4, sys::virtual_key::NUMPAD4},
49 {GLFW_KEY_KP_5, sys::virtual_key::NUMPAD5}, {GLFW_KEY_KP_6, sys::virtual_key::NUMPAD6},
50 {GLFW_KEY_KP_7, sys::virtual_key::NUMPAD7}, {GLFW_KEY_KP_8, sys::virtual_key::NUMPAD8},
51 {GLFW_KEY_KP_9, sys::virtual_key::NUMPAD9}, {GLFW_KEY_KP_DECIMAL, sys::virtual_key::DECIMAL},
52 {GLFW_KEY_KP_DIVIDE, sys::virtual_key::DIVIDE}, {GLFW_KEY_KP_MULTIPLY, sys::virtual_key::MULTIPLY},
53 {GLFW_KEY_KP_SUBTRACT, sys::virtual_key::SUBTRACT}, {GLFW_KEY_KP_ADD, sys::virtual_key::ADD},
54 {GLFW_KEY_KP_ENTER, sys::virtual_key::RETURN}, {GLFW_KEY_LEFT_SHIFT, sys::virtual_key::LSHIFT},
55 {GLFW_KEY_LEFT_CONTROL, sys::virtual_key::LCONTROL}, {GLFW_KEY_LEFT_ALT, sys::virtual_key::LMENU},
56 {GLFW_KEY_LEFT_SUPER, sys::virtual_key::LWIN}, {GLFW_KEY_RIGHT_SHIFT, sys::virtual_key::RSHIFT},
57 {GLFW_KEY_RIGHT_CONTROL, sys::virtual_key::RCONTROL}, {GLFW_KEY_RIGHT_ALT, sys::virtual_key::RMENU},
58 {GLFW_KEY_RIGHT_SUPER, sys::virtual_key::RWIN}, {GLFW_KEY_MENU, sys::virtual_key::MENU}};
59
60bool is_key_depressed(sys::state const& game_state, sys::virtual_key key) {
61 for(auto it = glfw_key_to_virtual_key.begin(); it != glfw_key_to_virtual_key.end(); ++it)
62 if(it->second == key)
63 return glfwGetKey(game_state.win_ptr->window, it->first) == GLFW_PRESS;
64
65 return false;
66}
67
68void get_window_size(sys::state const& game_state, int& width, int& height) {
69 glfwGetWindowSize(game_state.win_ptr->window, &width, &height);
70}
71
72bool is_in_fullscreen(sys::state const& game_state) {
73 return (game_state.win_ptr) && game_state.win_ptr->in_fullscreen;
74}
75
76void set_borderless_full_screen(sys::state& game_state, bool fullscreen) {
77 if(game_state.win_ptr && game_state.win_ptr->window) {
78 // Unsure how it works, but it works
79 sys::state* state = (sys::state*)glfwGetWindowUserPointer(game_state.win_ptr->window);
80 int width, height;
81 glfwGetFramebufferSize(game_state.win_ptr->window, &width, &height);
82 state->x_size = width;
83 state->y_size = height;
84
85 GLFWmonitor* monitor = glfwGetPrimaryMonitor();
86
87 if(fullscreen) {
88 glfwGetWindowSize(game_state.win_ptr->window, &width, &height);
89 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
90 glfwSetWindowMonitor(game_state.win_ptr->window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
91 game_state.win_ptr->in_fullscreen=true;
92 } else {
93 const GLFWvidmode* mode = glfwGetVideoMode(monitor);
94 glfwSetWindowMonitor(game_state.win_ptr->window, nullptr, 0, 0, width, height, mode->refreshRate);
95 glfwMaximizeWindow(game_state.win_ptr->window);
96 game_state.win_ptr->in_fullscreen=false;
97 }
98 }
99}
100
101void close_window(sys::state& game_state) {
102 // Signal to close window (should close = yes)
103 glfwSetWindowShouldClose(game_state.win_ptr->window, 1);
104}
105
107 bool control =
108 (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS);
109 bool alt = (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS);
110 bool shift =
111 (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
115 return sys::key_modifiers(val);
116}
117
119 uint32_t val =
123 return sys::key_modifiers(val);
124}
125
126static void glfw_error_callback(int error, char const* description) {
127 emit_error_message(std::string{ "Glfw Error " } + std::to_string(error) + std::string{ description }, false);
128}
129
130static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
131 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
132
133 sys::virtual_key virtual_key = glfw_key_to_virtual_key.at(key);
134 switch(action) {
135 case GLFW_PRESS:
136 state->on_key_down(virtual_key, get_current_modifiers(mods));
137 break;
138 case GLFW_RELEASE:
139 state->on_key_up(virtual_key, get_current_modifiers(mods));
140 break;
141 case GLFW_REPEAT:
142 switch(virtual_key) {
143 case sys::virtual_key::RETURN: [[fallthrough]];
144 case sys::virtual_key::BACK: [[fallthrough]];
145 case sys::virtual_key::DELETE_KEY: [[fallthrough]];
146 case sys::virtual_key::LEFT: [[fallthrough]];
147 case sys::virtual_key::RIGHT: [[fallthrough]];
148 case sys::virtual_key::UP: [[fallthrough]];
150 state->on_key_down(virtual_key, get_current_modifiers(mods));
151 break;
152 default:
153 break;
154 }
155 break;
156 default:
157 break;
158 }
159}
160
161static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
162 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
163
164 int32_t x = (xpos > 0 ? (int32_t)std::round(xpos) : 0);
165 int32_t y = (ypos > 0 ? (int32_t)std::round(ypos) : 0);
166 state->on_mouse_move(x, y, get_current_modifiers(window));
167
168 if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
169 state->on_mouse_drag(x, y, get_current_modifiers(window));
170
171 state->mouse_x_position = x;
172 state->mouse_y_position = y;
173}
174
175void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
176 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
177
178 double xpos, ypos;
179 glfwGetCursorPos(window, &xpos, &ypos);
180 int32_t x = (xpos > 0 ? (int32_t)std::round(xpos) : 0);
181 int32_t y = (ypos > 0 ? (int32_t)std::round(ypos) : 0);
182
183 switch(action) {
184 case GLFW_PRESS:
185 if(button == GLFW_MOUSE_BUTTON_LEFT) {
186 state->on_lbutton_down(x, y, get_current_modifiers(window));
187 state->win_ptr->left_mouse_down = true;
188 } else if(button == GLFW_MOUSE_BUTTON_RIGHT) {
189 state->on_rbutton_down(x, y, get_current_modifiers(window));
190 } else if(button == GLFW_MOUSE_BUTTON_MIDDLE) {
191 state->on_mbutton_down(x, y, get_current_modifiers(window));
192 }
193 state->mouse_x_position = x;
194 state->mouse_y_position = y;
195 break;
196 case GLFW_RELEASE:
197 if(button == GLFW_MOUSE_BUTTON_LEFT) {
198 state->on_lbutton_up(x, y, get_current_modifiers(window));
199 state->win_ptr->left_mouse_down = false;
200 } else if(button == GLFW_MOUSE_BUTTON_RIGHT) {
201 state->on_rbutton_up(x, y, get_current_modifiers(window));
202 } else if(button == GLFW_MOUSE_BUTTON_MIDDLE) {
203 state->on_mbutton_up(x, y, get_current_modifiers(window));
204 }
205 state->mouse_x_position = x;
206 state->mouse_y_position = y;
207 break;
208 }
209}
210
211void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
212 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
213
214 double xpos, ypos;
215 glfwGetCursorPos(window, &xpos, &ypos);
216 int32_t x = (xpos > 0 ? (int32_t)std::round(xpos) : 0);
217 int32_t y = (ypos > 0 ? (int32_t)std::round(ypos) : 0);
218
219 state->on_mouse_wheel(x, y, get_current_modifiers(window), (float)yoffset);
220 state->mouse_x_position = x;
221 state->mouse_y_position = y;
222}
223
224void character_callback(GLFWwindow* window, unsigned int codepoint) {
225 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
226 if(state->ui_state.edit_target) {
227 state->on_text(codepoint);
228 }
229}
230
231void on_window_change(GLFWwindow* window) {
232 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
233
235 if(glfwGetWindowAttrib(window, GLFW_MAXIMIZED) == GLFW_MAXIMIZED)
237 else if(glfwGetWindowAttrib(window, GLFW_ICONIFIED) == GLFW_ICONIFIED)
239
240 // redo OpenGL viewport
241 int width, height;
242 glfwGetFramebufferSize(window, &width, &height);
243 state->on_resize(width, height, t);
244 state->x_size = width;
245 state->y_size = height;
246}
247
248void window_size_callback(GLFWwindow* window, int width, int height) {
249 // on_window_change(window);
250 // framebuffer_size_callback should be enough
251}
252
253void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
255}
256
257void window_iconify_callback(GLFWwindow* window, int iconified) {
259}
260
263}
264
265void focus_callback(GLFWwindow* window, int focused) {
266 sys::state* state = (sys::state*)glfwGetWindowUserPointer(window);
267 if(focused) {
268 if(state->user_settings.mute_on_focus_lost) {
269 sound::resume_all(*state);
270 }
271 } else {
272 if(state->user_settings.mute_on_focus_lost) {
273 sound::pause_all(*state);
274 }
275 }
276}
277
278void create_window(sys::state& game_state, creation_parameters const& params) {
279 game_state.win_ptr = std::make_unique<window_data_impl>();
280 game_state.win_ptr->creation_x_size = params.size_x;
281 game_state.win_ptr->creation_y_size = params.size_y;
282 game_state.win_ptr->in_fullscreen = params.borderless_fullscreen;
283
284 // Setup window
285 glfwSetErrorCallback(glfw_error_callback);
286 if(!glfwInit())
287 emit_error_message("Failed to init glfw\n", true);
288
289 glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
290 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
291 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
292 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
293 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
294 //glfwWindowHint(GLFW_SAMPLES, game_state.user_settings.antialias_level);
295
296 // Create window with graphics context
297 auto* window = glfwCreateWindow(params.size_x, params.size_y, "Project Alice", NULL, NULL);
298 if(window == NULL)
299 emit_error_message("Failed to create window\n", true);
300 game_state.win_ptr->window = window;
301
302 glfwSetWindowUserPointer(window, &game_state);
303
304
305 // event callbacks
306 glfwSetKeyCallback(window, key_callback);
307 glfwSetCursorPosCallback(window, cursor_position_callback);
308 glfwSetMouseButtonCallback(window, mouse_button_callback);
309 glfwSetScrollCallback(window, scroll_callback);
310 glfwSetCharCallback(window, character_callback);
311 glfwSetWindowSizeCallback(window, window_size_callback);
312 glfwSetWindowIconifyCallback(window, window_iconify_callback);
313 glfwSetWindowMaximizeCallback(window, window_maximize_callback);
314 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
315 glfwSetWindowFocusCallback(window, focus_callback);
316 glfwSetWindowSizeLimits(window, 640, 400, 2400, 1800);
317 if(params.borderless_fullscreen){
318 int width, height;
319 glfwGetFramebufferSize(game_state.win_ptr->window, &width, &height);
320 glfwGetWindowSize(game_state.win_ptr->window, &width, &height);
321 const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
322 glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, mode->width, mode->height, mode->refreshRate);
323 game_state.win_ptr->in_fullscreen=true;
324 }
325
326 ogl::initialize_opengl(game_state);
327
329 sound::start_music(game_state, game_state.user_settings.master_volume * game_state.user_settings.music_volume);
330
331 on_window_change(window); // Init the window size
332
333 change_cursor(game_state, cursor_type::busy);
334 game_state.on_create();
336
337 while(!glfwWindowShouldClose(window)) {
338 glfwPollEvents();
339 // Run game code
340
341 game_state.render();
342 glfwSwapBuffers(window);
343
344 sound::update_music_track(game_state);
345 }
346
347 glfwDestroyWindow(window);
348 glfwTerminate();
349}
350
352 //TODO: Implement on linux
353}
354
355void emit_error_message(std::string const& content, bool fatal) {
356 std::fprintf(stderr, "%s", content.c_str());
357 if(fatal) {
358 std::exit(EXIT_FAILURE);
359 }
360}
361
362} // namespace window
void initialize_opengl(sys::state &state)
void pause_all(sys::state &state)
Definition: sound_nix.cpp:226
void initialize_sound_system(sys::state &state)
Definition: sound_nix.cpp:84
void resume_all(sys::state &state)
Definition: sound_nix.cpp:240
void update_music_track(sys::state &state)
Definition: sound_nix.cpp:255
void start_music(sys::state &state, float v)
Definition: sound_nix.cpp:214
virtual_key
Definition: constants.hpp:5
key_modifiers
Definition: constants.hpp:156
window_state
Definition: window.hpp:46
void set_borderless_full_screen(sys::state &game_state, bool fullscreen)
Definition: window_nix.cpp:76
void get_window_size(sys::state const &game_state, int &width, int &height)
Definition: window_nix.cpp:68
bool is_key_depressed(sys::state const &game_state, sys::virtual_key key)
Definition: window_nix.cpp:60
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
Definition: window_nix.cpp:253
bool is_in_fullscreen(sys::state const &game_state)
Definition: window_nix.cpp:72
sys::key_modifiers get_current_modifiers()
Definition: window_win.cpp:92
void window_maximize_callback(GLFWwindow *window, int maximized)
Definition: window_nix.cpp:261
void emit_error_message(std::string const &content, bool fatal)
Definition: window_nix.cpp:355
void window_size_callback(GLFWwindow *window, int width, int height)
Definition: window_nix.cpp:248
void close_window(sys::state &game_state)
Definition: window_nix.cpp:101
void focus_callback(GLFWwindow *window, int focused)
Definition: window_nix.cpp:265
void window_iconify_callback(GLFWwindow *window, int iconified)
Definition: window_nix.cpp:257
void change_cursor(sys::state &state, cursor_type type)
Definition: window_nix.cpp:351
void on_window_change(GLFWwindow *window)
Definition: window_nix.cpp:231
cursor_type
Definition: window.hpp:61
void mouse_button_callback(GLFWwindow *window, int button, int action, int mods)
Definition: window_nix.cpp:175
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset)
Definition: window_nix.cpp:211
void create_window(sys::state &game_state, creation_parameters const &params)
Definition: window_nix.cpp:278
void character_callback(GLFWwindow *window, unsigned int codepoint)
Definition: window_nix.cpp:224
uint uint32_t
user_settings_s user_settings
void on_create()
std::unique_ptr< window::window_data_impl > win_ptr