Kale
Loading...
Searching...
No Matches
WindowGLFW.cpp
Go to the documentation of this file.
1/*
2 Copyright 2022 Rishi Challa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifdef KALE_GLFW
18
22
23#include <stdexcept>
24
25#define STB_IMAGE_IMPLEMENTATION
26#include <stb_image/stb_image.h>
27
28using namespace Kale;
29
30static std::list<EventHandler*>* handlers = nullptr;
31static Vector2ui oldWinSize(800, 450);
32
36struct _WinGamePad {
37 unsigned int id;
41 A, B, X, Y,
42 R1, L1;
43 Vector2f lJoystick, rJoystick;
44 float lHandle, rHandle;
45
46 _WinGamePad(unsigned int id) : id(id) {}
47};
48
49static std::list<_WinGamePad> gamePads;
50
54Window::Window() {
55 glfwInit();
56
57#ifdef KALE_OPENGL
58
59 // Mac drivers of OpenGL are stale and only support up to 4.1
60#ifdef KALE_OSX
61 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
62 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
63#else
64 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
65 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
66#endif
67
68 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
69 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
70
71#ifdef KALE_DEBUG
72 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
73#endif
74
75#endif
76
77#ifdef KALE_VULKAN
78 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
79#endif
80
81 glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
82}
83
87Window::~Window() {
88 glfwDestroyWindow(window);
89 glfwTerminate();
90 handlers = nullptr;
91}
92
93static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
94 if (handlers == nullptr) return;
95 Key eKey;
96
97 switch (key) {
98 case GLFW_KEY_GRAVE_ACCENT: eKey = Key::Backtick; break;
99 case GLFW_KEY_1: eKey = Key::One; break;
100 case GLFW_KEY_2: eKey = Key::Two; break;
101 case GLFW_KEY_3: eKey = Key::Three; break;
102 case GLFW_KEY_4: eKey = Key::Four; break;
103 case GLFW_KEY_5: eKey = Key::Five; break;
104 case GLFW_KEY_6: eKey = Key::Six; break;
105 case GLFW_KEY_7: eKey = Key::Seven; break;
106 case GLFW_KEY_8: eKey = Key::Eight; break;
107 case GLFW_KEY_9: eKey = Key::Nine; break;
108 case GLFW_KEY_0: eKey = Key::Zero; break;
109 case GLFW_KEY_MINUS: eKey = Key::Minus; break;
110 case GLFW_KEY_EQUAL: eKey = Key::Equals; break;
111 case GLFW_KEY_BACKSPACE: case GLFW_KEY_DELETE: eKey = Key::Backspace; break;
112 case GLFW_KEY_TAB: eKey = Key::Tab; break;
113 case GLFW_KEY_LEFT_BRACKET: eKey = Key::LeftBracket; break;
114 case GLFW_KEY_RIGHT_BRACKET: eKey = Key::RightBracket; break;
115 case GLFW_KEY_BACKSLASH: eKey = Key::Backslash; break;
116 case GLFW_KEY_ENTER: eKey = Key::Enter; break;
117 case GLFW_KEY_LEFT_SHIFT: eKey = Key::LeftShift; break;
118 case GLFW_KEY_COMMA: eKey = Key::Comma; break;
119 case GLFW_KEY_PERIOD: eKey = Key::Period; break;
120 case GLFW_KEY_SLASH: eKey = Key::Slash; break;
121 case GLFW_KEY_RIGHT_SHIFT: eKey = Key::RightShift; break;
122 case GLFW_KEY_LEFT_CONTROL: case GLFW_KEY_RIGHT_CONTROL: eKey = Key::Control; break;
123 case GLFW_KEY_LEFT_ALT: case GLFW_KEY_RIGHT_ALT: eKey = Key::Alt; break;
124 case GLFW_KEY_SPACE: eKey = Key::Space; break;
125 case GLFW_KEY_UP: eKey = Key::Up; break;
126 case GLFW_KEY_DOWN: eKey = Key::Down; break;
127 case GLFW_KEY_LEFT: eKey = Key::Left; break;
128 case GLFW_KEY_RIGHT: eKey = Key::Right; break;
129 case GLFW_KEY_Q: eKey = Key::Q; break;
130 case GLFW_KEY_W: eKey = Key::W; break;
131 case GLFW_KEY_E: eKey = Key::E; break;
132 case GLFW_KEY_R: eKey = Key::R; break;
133 case GLFW_KEY_T: eKey = Key::T; break;
134 case GLFW_KEY_Y: eKey = Key::Y; break;
135 case GLFW_KEY_U: eKey = Key::U; break;
136 case GLFW_KEY_I: eKey = Key::I; break;
137 case GLFW_KEY_O: eKey = Key::O; break;
138 case GLFW_KEY_P: eKey = Key::P; break;
139 case GLFW_KEY_A: eKey = Key::A; break;
140 case GLFW_KEY_S: eKey = Key::S; break;
141 case GLFW_KEY_D: eKey = Key::D; break;
142 case GLFW_KEY_F: eKey = Key::F; break;
143 case GLFW_KEY_G: eKey = Key::G; break;
144 case GLFW_KEY_H: eKey = Key::H; break;
145 case GLFW_KEY_J: eKey = Key::J; break;
146 case GLFW_KEY_K: eKey = Key::K; break;
147 case GLFW_KEY_L: eKey = Key::L; break;
148 case GLFW_KEY_Z: eKey = Key::Z; break;
149 case GLFW_KEY_X: eKey = Key::X; break;
150 case GLFW_KEY_C: eKey = Key::C; break;
151 case GLFW_KEY_V: eKey = Key::V; break;
152 case GLFW_KEY_B: eKey = Key::B; break;
153 case GLFW_KEY_N: eKey = Key::N; break;
154 case GLFW_KEY_M: eKey = Key::M; break;
155 default: return;
156 }
157
158 if (action == GLFW_PRESS) for (auto handler : *handlers) handler->onKeyPress(eKey);
159 if (action == GLFW_RELEASE) for (auto handler : *handlers) handler->onKeyRelease(eKey);
160}
161
162static void cursorCallback(GLFWwindow* window, double x, double y) {
163 if (handlers == nullptr) return;
164 Vector2f pos = Vector2d(x, y).cast<float>();
165 for (auto handler : *handlers) handler->onMouseMove(pos);
166}
167
168static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) {
169 if (handlers == nullptr) return;
170 switch (action) {
171 case GLFW_PRESS:
172 switch (button) {
173 case GLFW_MOUSE_BUTTON_LEFT: for (auto handler : *handlers) handler->onLeftClick(); return;
174 case GLFW_MOUSE_BUTTON_MIDDLE: for (auto handler : *handlers) handler->onMiddleClick(); return;
175 case GLFW_MOUSE_BUTTON_RIGHT: for (auto handler : *handlers) handler->onRightClick(); return;
176 default: return;
177 }
178 case GLFW_RELEASE:
179 switch (button) {
180 case GLFW_MOUSE_BUTTON_LEFT: for (auto handler : *handlers) handler->onLeftClickRelease(); return;
181 case GLFW_MOUSE_BUTTON_MIDDLE: for (auto handler : *handlers) handler->onMiddleClickRelease(); return;
182 case GLFW_MOUSE_BUTTON_RIGHT: for (auto handler : *handlers) handler->onRightClickRelease(); return;
183 default: return;
184 }
185 default: return;
186 }
187}
188
189static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
190 if (handlers == nullptr) return;
191 for (auto handler : *handlers) handler->onMouseScroll(static_cast<float>(yoffset));
192}
193
194static void resizeCallback(GLFWwindow* window, int width, int height) {
195 Vector2ui tmp_oldWinSize(oldWinSize);
196 Vector2ui size = Vector2i(width, height).cast<unsigned int>();
197 // Set the oldWinSize static variable here to avoid client calling getSize() and retrieving incorrect size
198 oldWinSize = size;
199
200 if (handlers == nullptr) return;
201 for (auto handler : *handlers) handler->onWindowResize(tmp_oldWinSize, size);
202}
203
204static void focusCallback(GLFWwindow* window, int focused) {
205 if (handlers == nullptr) return;
206 if (focused) for (auto handler : *handlers) handler->onWindowGainedFocus();
207 else for (auto handler : *handlers) handler->onWindowLostFocus();
208}
209
210static void joystickCallback(int jid, int action) {
211 if (handlers == nullptr) return;
212 switch (action) {
213 case GLFW_CONNECTED:
214 for (auto handler : *handlers) handler->onControllerConnect(jid);
215 gamePads.emplace_back(jid);
216 return;
217 case GLFW_DISCONNECTED:
218 for (auto handler : *handlers) handler->onControllerDisconnect(jid);
219 gamePads.remove_if([=] (_WinGamePad& gamepad) {
220 return gamepad.id == jid;
221 });
222 return;
223 default:
224 return;
225 }
226}
227
233void Window::create(const char* title) {
234 this->title = title;
235 window = glfwCreateWindow(oldWinSize.x, oldWinSize.y, title, nullptr, nullptr);
236
237 if (!window) {
238 glfwTerminate();
239 console.error("Unable to create GLFW window");
240 exit(0);
241 }
242
243 // Set the default window icon to the Kale icon
244 setIcon(mainApp->getAssetFolderPath() + "textures/kale.png");
245
246#ifdef KALE_OPENGL
247 glfwMakeContextCurrent(window);
248 glfwSwapInterval(1);
249#endif
250
251 // Correct the oldWinSize static variable to the window size rather than framebuffer size
252 Vector2i winSize;
253 glfwGetWindowSize(window, &winSize.x, &winSize.y);
254 oldWinSize = winSize.cast<unsigned int>();
255
256 handlers = &eventHandlers;
257 glfwSetKeyCallback(window, keyCallback);
258 glfwSetCursorPosCallback(window, cursorCallback);
259 glfwSetMouseButtonCallback(window, mouseButtonCallback);
260 glfwSetScrollCallback(window, scrollCallback);
261 glfwSetWindowSizeCallback(window, resizeCallback);
262 glfwSetWindowFocusCallback(window, focusCallback);
263 glfwSetJoystickCallback(joystickCallback);
264}
265
270bool Window::isOpen() const {
271 return !glfwWindowShouldClose(window);
272}
273
277void Window::lockCursor() {
278 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
279}
280
284void Window::unlockCursor() {
285 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
286}
287
291Vector2ui Window::getSize() const {
292 return oldWinSize;
293}
294
298Vector2f Window::getSizeF() const {
299 return oldWinSize.cast<float>();
300}
301
305Vector2ui Window::getFramebufferSize() const {
306 Vector2i size;
307 glfwGetFramebufferSize(window, &size.x, &size.y);
308 return size.cast<unsigned int>();
309}
310
314void Window::update() {
315
316 // Poll Events
317 glfwPollEvents();
318
319 // Gamepad input
320 for (_WinGamePad& gamepad : gamePads) {
321 GLFWgamepadstate state;
322 if (!glfwGetGamepadState(gamepad.id, &state)) {
323 gamePads.remove_if([&] (_WinGamePad& gamepad2) {
324 return gamepad2.id == gamepad.id;
325 });
326 continue;
327 }
328
329 // Gamepad Buttons
330 if (state.buttons[GLFW_GAMEPAD_BUTTON_A] == GLFW_PRESS && !gamepad.A) {
331 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::A);
332 gamepad.A = true;
333 }
334 if (state.buttons[GLFW_GAMEPAD_BUTTON_B] == GLFW_PRESS && !gamepad.B) {
335 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::B);
336 gamepad.B = true;
337 }
338 if (state.buttons[GLFW_GAMEPAD_BUTTON_X] == GLFW_PRESS && !gamepad.X) {
339 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::X);
340 gamepad.X = true;
341 }
342 if (state.buttons[GLFW_GAMEPAD_BUTTON_Y] == GLFW_PRESS && !gamepad.Y) {
343 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::Y);
344 gamepad.Y = true;
345 }
346 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_UP] == GLFW_PRESS && !gamepad.DPadUp) {
347 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::DPadUp);
348 gamepad.DPadUp = true;
349 }
350 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT] == GLFW_PRESS && !gamepad.DPadRight) {
351 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::DPadRight);
352 gamepad.DPadRight = true;
353 }
354 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_DOWN] == GLFW_PRESS && !gamepad.DPadDown) {
355 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::DPadDown);
356 gamepad.DPadDown = true;
357 }
358 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT] == GLFW_PRESS && !gamepad.DPadLeft) {
359 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::DPadLeft);
360 gamepad.DPadLeft = true;
361 }
362 if (state.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER] == GLFW_PRESS && !gamepad.R1) {
363 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::R1);
364 gamepad.R1 = true;
365 }
366 if (state.buttons[GLFW_GAMEPAD_BUTTON_LEFT_BUMPER] == GLFW_PRESS && !gamepad.L1) {
367 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::L1);
368 gamepad.L1 = true;
369 }
370 if (state.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_THUMB] == GLFW_PRESS && !gamepad.RightJoystick) {
371 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::RightJoystick);
372 gamepad.RightJoystick = true;
373 }
374 if (state.buttons[GLFW_GAMEPAD_BUTTON_LEFT_THUMB] == GLFW_PRESS && !gamepad.LeftJoystick) {
375 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::LeftJoystick);
376 gamepad.LeftJoystick = true;
377 }
378 if (state.buttons[GLFW_GAMEPAD_BUTTON_START] == GLFW_PRESS && !gamepad.RightMenu) {
379 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::RightMenu);
380 gamepad.RightMenu = true;
381 }
382 if (state.buttons[GLFW_GAMEPAD_BUTTON_GUIDE] == GLFW_PRESS && !gamepad.LeftMenu) {
383 for (auto handler : eventHandlers) handler->onControllerButtonPress(gamepad.id, ControllerButton::LeftMenu);
384 gamepad.LeftMenu = true;
385 }
386
387
388 if (state.buttons[GLFW_GAMEPAD_BUTTON_A] == GLFW_RELEASE && gamepad.A) {
389 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::A);
390 gamepad.A = false;
391 }
392 if (state.buttons[GLFW_GAMEPAD_BUTTON_B] == GLFW_RELEASE && gamepad.B) {
393 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::B);
394 gamepad.B = false;
395 }
396 if (state.buttons[GLFW_GAMEPAD_BUTTON_X] == GLFW_RELEASE && gamepad.X) {
397 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::X);
398 gamepad.X = false;
399 }
400 if (state.buttons[GLFW_GAMEPAD_BUTTON_Y] == GLFW_RELEASE && gamepad.Y) {
401 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::Y);
402 gamepad.Y = false;
403 }
404 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_UP] == GLFW_RELEASE && gamepad.DPadUp) {
405 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::DPadUp);
406 gamepad.DPadUp = false;
407 }
408 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT] == GLFW_RELEASE && gamepad.DPadRight) {
409 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::DPadRight);
410 gamepad.DPadRight = false;
411 }
412 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_DOWN] == GLFW_RELEASE && gamepad.DPadDown) {
413 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::DPadDown);
414 gamepad.DPadDown = false;
415 }
416 if (state.buttons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT] == GLFW_RELEASE && gamepad.DPadLeft) {
417 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::DPadLeft);
418 gamepad.DPadLeft = false;
419 }
420 if (state.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER] == GLFW_RELEASE && gamepad.R1) {
421 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::R1);
422 gamepad.R1 = false;
423 }
424 if (state.buttons[GLFW_GAMEPAD_BUTTON_LEFT_BUMPER] == GLFW_RELEASE && gamepad.L1) {
425 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::L1);
426 gamepad.L1 = false;
427 }
428 if (state.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_THUMB] == GLFW_RELEASE && gamepad.RightJoystick) {
429 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::RightJoystick);
430 gamepad.RightJoystick = false;
431 }
432 if (state.buttons[GLFW_GAMEPAD_BUTTON_LEFT_THUMB] == GLFW_RELEASE && gamepad.LeftJoystick) {
433 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::LeftJoystick);
434 gamepad.LeftJoystick = false;
435 }
436 if (state.buttons[GLFW_GAMEPAD_BUTTON_START] == GLFW_RELEASE && gamepad.RightMenu) {
437 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::RightMenu);
438 gamepad.RightMenu = false;
439 }
440 if (state.buttons[GLFW_GAMEPAD_BUTTON_GUIDE] == GLFW_RELEASE && gamepad.LeftMenu) {
441 for (auto handler : eventHandlers) handler->onControllerButtonRelease(gamepad.id, ControllerButton::LeftMenu);
442 gamepad.LeftMenu = false;
443 }
444
445 // Handles
446 if (state.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER] != gamepad.lHandle) {
447 gamepad.lHandle = state.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER];
448 for (auto handler : eventHandlers) handler->onControllerHandle(gamepad.id, ControllerAxis::Left, gamepad.lHandle);
449 }
450 if (state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER] != gamepad.rHandle) {
451 gamepad.lHandle = state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER];
452 for (auto handler : eventHandlers) handler->onControllerHandle(gamepad.id, ControllerAxis::Right, gamepad.rHandle);
453 }
454
455 // Joysticks
456 if (state.axes[GLFW_GAMEPAD_AXIS_LEFT_X] != gamepad.lJoystick.x || state.axes[GLFW_GAMEPAD_AXIS_LEFT_Y] != gamepad.lJoystick.y) {
457 gamepad.lJoystick.x = state.axes[GLFW_GAMEPAD_AXIS_LEFT_X];
458 gamepad.lJoystick.y = state.axes[GLFW_GAMEPAD_AXIS_LEFT_Y];
459 for (auto handler : eventHandlers) handler->onControllerJoystick(gamepad.id, ControllerAxis::Left, gamepad.lJoystick);
460 }
461 if (state.axes[GLFW_GAMEPAD_AXIS_RIGHT_X] != gamepad.rJoystick.x || state.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y] != gamepad.rJoystick.y) {
462 gamepad.rJoystick.x = state.axes[GLFW_GAMEPAD_AXIS_RIGHT_X];
463 gamepad.rJoystick.y = state.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y];
464 for (auto handler : eventHandlers) handler->onControllerJoystick(gamepad.id, ControllerAxis::Right, gamepad.rJoystick);
465 }
466 }
467}
468
473std::vector<const char*> Window::getInstanceExtensions() const {
474 uint32_t glfwExtensionCount = 0;
475 const char** glfwExtensions;
476 glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
477 std::vector<const char*> requiredExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
478 return requiredExtensions;
479}
480
481#ifdef KALE_VULKAN
482
489void Window::createWindowSurface(const vk::UniqueInstance& instance, vk::UniqueSurfaceKHR& surface) const {
490 VkSurfaceKHR tmpSurface;
491 if (glfwCreateWindowSurface(instance.get(), window, nullptr, &tmpSurface) != VK_SUCCESS)
492 throw std::runtime_error("Unable to create window surface");
493
494 surface = vk::UniqueSurfaceKHR(tmpSurface, instance.get());
495}
496
497#endif
498
499#ifdef KALE_OPENGL
500
505void Window::setupGlad() const {
506 if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress))
507 throw std::runtime_error("Unable to setup GLAD");
508}
509
513void Window::swapBuffers() const noexcept {
514 glfwSwapBuffers(window);
515}
516
517#endif
518
522const char* Window::getTitle() const {
523 return title;
524}
525
530void Window::setIcon(const std::string& filePath) {
531
532#ifndef KALE_OSX
533 GLFWimage image;
534 image.pixels = stbi_load(filePath.c_str(), &image.width, &image.height, nullptr, STBI_rgb_alpha);
535 glfwSetWindowIcon(window, 1, &image);
536 stbi_image_free(image.pixels);
537#else
538 console.warn("Cannot set icon to " + filePath + " - OSX does not support glfwSetWindowIcon");
539#endif
540
541}
542
543#endif
std::string getAssetFolderPath() const
void warn(T msg)
Definition Logger.hpp:182
void error(T msg)
Definition Logger.hpp:198
Vector2< A > cast() const
Definition Vector.hpp:144
ControllerButton
Definition Events.hpp:33
Application * mainApp
ControllerAxis
Definition Events.hpp:26
Logger console
Definition Logger.hpp:317