CoriEngine
Loading...
Searching...
No Matches
Window.cpp
Go to the documentation of this file.
1#include "Window.hpp"
3#include <backends/imgui_impl_sdl3.h>
4#include <SDL3_image/SDL_image.h>
10
11namespace Cori {
12 namespace Core {
13 struct Window::Data {
14 std::vector<ScreenMode> m_ScreenModes;
17 std::string m_WindowTitle;
18
20 SDL_DisplayMode** m_SDLModes{ nullptr };
21 SDL_DisplayID m_PrimaryDisplayID{};
22
23 SDL_Window* m_Window{ nullptr };
24 std::unique_ptr<Graphics::RenderingContext> m_Context;
25 bool m_VSync{ false };
26
28
30 SDL_DestroyWindow(m_Window);
31 SDL_free(m_SDLModes);
32 }
33 };
34
35 std::unique_ptr<Window> Window::Create(std::string name, const bool vsync) {
36 return std::unique_ptr<Window>(new Window(std::move(name), vsync));
37 }
38
39 Window::Window(std::string title, const bool vsync) {
40 m_Data = new Data();
41 m_Data->m_WindowTitle = std::move(title);
42 m_Data->m_VSync = vsync;
43
45
46
47 const SDL_DisplayID primaryDisplayID = SDL_GetPrimaryDisplay();
48 if (primaryDisplayID == 0) {
49 CORI_CORE_FATAL_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to get primary display ID. SDL_Error: {}", SDL_GetError());
50 }
51 else {
52 m_Data->m_PrimaryDisplayID = primaryDisplayID;
53 }
54
55 m_Data->m_SDLModes = SDL_GetFullscreenDisplayModes(m_Data->m_PrimaryDisplayID, &m_Data->m_DisplayModeCount);
56
57 CORI_CORE_VERIFY(m_Data->m_SDLModes, "Failed to get screen modes, Window '{}' can not be created. SDL_Error: {}", title, SDL_GetError());
58
59 for (int32_t i = 0; i < m_Data->m_DisplayModeCount; i++) {
60 ScreenMode mode(m_Data->m_SDLModes[i]->w, m_Data->m_SDLModes[i]->h, m_Data->m_SDLModes[i]->refresh_rate, i);
61 m_Data->m_ScreenModes.emplace_back(mode);
62 }
63
64 ScreenMode mode = m_Data->m_ScreenModes[0];
65
66 const std::filesystem::path savePath = FileSystem::PathManager::GetAliasedPath("USER_DATA") / "settings/window.bin";
67 std::filesystem::create_directories(savePath.parent_path());
68
69 bool configLoaded = false;
70
71 if (std::filesystem::exists(savePath)) {
73 if (data) {
74 if (m_Data->m_DisplayModeCount >= data->m_SDLModeIndex) {
75 if (m_Data->m_SDLModes[data->m_SDLModeIndex]->w == data->m_Width && m_Data->m_SDLModes[data->m_SDLModeIndex]->h == data->m_Height && m_Data->m_SDLModes[data->m_SDLModeIndex]->refresh_rate == data->m_RefreshRate &&
76 m_Data->m_ScreenModes[data->m_ModeIndex].m_Width == data->m_Width && m_Data->m_ScreenModes[data->m_ModeIndex].m_Height == data->m_Height && m_Data->m_ScreenModes[data->m_ModeIndex].m_RefreshRate == data->m_RefreshRate) {
77 mode.m_Width = data->m_Width;
78 mode.m_Height = data->m_Height;
79 mode.m_RefreshRate = data->m_RefreshRate;
80 mode.m_SDLModeIndex = data->m_SDLModeIndex;
81 m_Data->m_CurrentWindowMode = data->m_WindowMode;
82 m_Data->m_CurrentScreenMode = data->m_ModeIndex;
83 configLoaded = true;
84 }
85 }
86 }
87 }
88
89 if (!configLoaded) {
90 m_Data->m_CurrentScreenMode = 0;
91 }
92
93 SDL_Rect displayBounds;
94 const bool success = SDL_GetDisplayBounds(m_Data->m_PrimaryDisplayID, &displayBounds);
95 if (!success) {
96 CORI_CORE_FATAL_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to get primary display bounds. SDL_Error: {}", SDL_GetError());
97 }
98
99 const SDL_PropertiesID props = SDL_CreateProperties();
100 SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, m_Data->m_WindowTitle.c_str());
101 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, m_Data->m_ScreenModes[0].m_Width);
102 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, m_Data->m_ScreenModes[0].m_Height);
103 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, displayBounds.x);
104 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, displayBounds.y);
105 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, true);
106
107 switch (s_API) {
109 CORI_CORE_ASSERT(false, "No graphics API selected");
110 break;
112 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
113 break;
115 CORI_CORE_ASSERT(false, "Vulkan is not supported, yet");
116 break;
117 }
118
119 m_Data->m_Window = SDL_CreateWindowWithProperties(props);
120
121 SDL_DestroyProperties(props);
122
123 CORI_CORE_ASSERT(m_Data->m_Window, "Failed to create Window '{}'. SDL_Error: {}", m_Data->m_WindowTitle, SDL_GetError());
124
125 const auto logoPath = FileSystem::PathManager::GetAliasedPath("ENGINE_DATA") / std::filesystem::path("ui/logo256.png");
126 SDL_Surface* logo = IMG_Load(logoPath.string().c_str());
127
128 if (!logo) {
129 CORI_CORE_ERROR_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to load App Logo: {}", SDL_GetError());
130 } else {
131 SDL_SetWindowIcon(m_Data->m_Window, logo);
132 }
133
134 SDL_DestroySurface(logo);
135
136 SDL_SetWindowPosition(m_Data->m_Window, SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID), SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID));
137
138 m_Data->m_Context->Init(m_Data->m_Window);
139
140 SetScreenMode(m_Data->m_CurrentScreenMode);
141
142 const WindowSaveData data{ .m_Width = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width, .m_Height = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height, .m_RefreshRate = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_RefreshRate, .m_WindowMode = m_Data->m_CurrentWindowMode, .m_SDLModeIndex = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_SDLModeIndex, .m_ModeIndex = m_Data->m_CurrentScreenMode };
144
145 CORI_CORE_INFO_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Window '{}' Created", m_Data->m_WindowTitle);
146 }
147
149 CORI_CORE_INFO_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Window '{}' Destroyed", m_Data->m_WindowTitle);
150 delete m_Data;
151 }
152
153 // ReSharper disable once CppMemberFunctionMayBeConst
154 void Window::OnUpdate() {
156 SDL_Event e;
157
158 while (SDL_PollEvent(&e)) {
159 ImGui_ImplSDL3_ProcessEvent(&e);
160
161 // ReSharper disable once CppDefaultCaseNotHandledInSwitchStatement
162 switch (e.type) {
163 case SDL_EVENT_WINDOW_RESIZED:
164 {
165 if (e.window.windowID != SDL_GetWindowID(m_Data->m_Window)) {
166 break;
167 }
168
169 WindowResizeEvent resizeEvent(GetWidth(), GetHeight());
170 m_Data->m_EventCallback(resizeEvent);
171
172 break;
173 }
174 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
175 {
176 WindowCloseEvent closeEvent;
177 m_Data->m_EventCallback(closeEvent);
178 break;
179 }
180 case SDL_EVENT_KEY_DOWN:
181 {
182 KeyPressedEvent keyPressedEvent(static_cast<CoriKeycode>(e.key.scancode), e.key.repeat);
183 m_Data->m_EventCallback(keyPressedEvent);
184 break;
185 }
186 case SDL_EVENT_KEY_UP:
187 {
188 KeyReleasedEvent keyReleasedEvent(static_cast<CoriKeycode>(e.key.scancode));
189 m_Data->m_EventCallback(keyReleasedEvent);
190 break;
191 }
192 case SDL_EVENT_MOUSE_MOTION:
193 {
194 MouseMovedEvent mouseMovedEvent(static_cast<int32_t>(e.motion.x), static_cast<int32_t>(e.motion.y));
195 m_Data->m_EventCallback(mouseMovedEvent);
196 break;
197 }
198 case SDL_EVENT_MOUSE_WHEEL:
199 {
200 MouseScrolledEvent mouseScrolledEvent(static_cast<int16_t>(e.wheel.x), static_cast<int16_t>(e.wheel.y));
201 m_Data->m_EventCallback(mouseScrolledEvent);
202 break;
203 }
204 case SDL_EVENT_MOUSE_BUTTON_DOWN:
205 {
206 MouseButtonPressedEvent mouseButtonPressedEvent(static_cast<CoriMouseKeycode>(e.button.button));
207 m_Data->m_EventCallback(mouseButtonPressedEvent);
208 break;
209 }
210 case SDL_EVENT_MOUSE_BUTTON_UP:
211 {
212 MouseButtonReleasedEvent mouseButtonReleasedEvent(static_cast<CoriMouseKeycode>(e.button.button));
213 m_Data->m_EventCallback(mouseButtonReleasedEvent);
214 break;
215 }
216 }
217 }
218
219 {
220 CORI_PROFILE_SCOPE("Swap Buffers");
221 m_Data->m_Context->SwapBuffers();
222 }
223 }
224
225 int32_t Window::GetWidth() const {
226 if (m_Data->m_CurrentWindowMode != WindowMode::BORDERLESS_WINDOWED) {
227 return m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width;
228 }
229 return m_Data->m_ScreenModes[0].m_Width;
230 }
231
232 int32_t Window::GetHeight() const {
233 if (m_Data->m_CurrentWindowMode != WindowMode::BORDERLESS_WINDOWED) {
234 return m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height;
235 }
236 return m_Data->m_ScreenModes[0].m_Height;
237 }
238
239 // ReSharper disable once CppMemberFunctionMayBeConst
240 void Window::SetEventCallback(const EventCallbackFn& callback) {
241 m_Data->m_EventCallback = callback;
242 }
243
244 // ReSharper disable once CppMemberFunctionMayBeConst
245 void Window::SetVSync(const bool status) {
246 if (!status) {
247 SDL_GL_SetSwapInterval(0);
248 }
249 else {
250 SDL_GL_SetSwapInterval(1);
251 }
252
253 m_Data->m_VSync = status;
254 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "VSync is now set to: {}", status);
255 }
256
257 bool Window::IsVSync() const {
258 return m_Data->m_VSync;
259 }
260
261
262 void* Window::GetNativeContext() const {
263 return m_Data->m_Context->GetNativeContext();
264 }
265
266 void* Window::GetNativeWindow() const {
267 return m_Data->m_Window;
268 }
269
270 const std::vector<ScreenMode>& Window::GetScreenModes() const {
271 return m_Data->m_ScreenModes;
272 }
273
274 std::expected<void, CoriError<>> Window::SetScreenMode(const uint32_t modeIndex) {
275 m_Data->m_CurrentScreenMode = modeIndex;
276 return SetWindowMode(m_Data->m_CurrentWindowMode);
277 }
278
280 return m_Data->m_CurrentWindowMode;
281 }
282
284 return m_Data->m_CurrentScreenMode;
285 }
286
287 // ReSharper disable once CppMemberFunctionMayBeConst
288 std::expected<void, CoriError<>> Window::SetWindowMode(const WindowMode mode) {
289 bool success;
290 switch (mode) {
292 {
293 success = SDL_SetWindowFullscreen(m_Data->m_Window, false);
294 if (!success) {
295 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Windowed'. SDL_Error: {}", SDL_GetError())));
296 }
297 const bool borderAdded = SDL_SetWindowBordered(m_Data->m_Window, true);
298 if (!borderAdded) {
299 CORI_CORE_WARN_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to add border to the window. SDL_Error: {}", SDL_GetError());
300 }
301
302 const SDL_DisplayMode* desktopMode = SDL_GetCurrentDisplayMode(m_Data->m_PrimaryDisplayID);
303
304 if (m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width <= desktopMode->w && m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height <= desktopMode->h) {
305 success = SDL_SetWindowSize(m_Data->m_Window, m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width, m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height);
306 if (!success) {
307 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Windowed'. SDL_Error: {}", SDL_GetError())));
308 }
309 }
310 else {
311 success = SDL_SetWindowSize(m_Data->m_Window, desktopMode->w, desktopMode->h);
312 if (!success) {
313 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Windowed'. SDL_Error: {}", SDL_GetError())));
314 }
315 }
316
317 const bool windowMoveSuccess = SDL_SetWindowPosition(m_Data->m_Window, SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID), SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID));
318 if (!windowMoveSuccess) {
319 CORI_CORE_WARN_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to set window position to the center of the main screen. (This is expected on Wayland) SDL_Error: {}", SDL_GetError());
320 }
321
322 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Window set to 'Windowed' mode. Screen mode: (Width: {}, Height: {})", desktopMode->w, desktopMode->h);
323
324 m_Data->m_CurrentWindowMode = mode;
325
326 const std::filesystem::path savePath = FileSystem::PathManager::GetAliasedPath("USER_DATA") / "settings/window.bin";
327 std::filesystem::create_directories(savePath.parent_path());
328 const WindowSaveData data{ .m_Width = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width, .m_Height = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height, .m_RefreshRate = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_RefreshRate, .m_WindowMode = m_Data->m_CurrentWindowMode, .m_SDLModeIndex = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_SDLModeIndex, .m_ModeIndex = m_Data->m_CurrentScreenMode };
330
331 break;
332 }
334 {
335 const bool windowMoveSuccess = SDL_SetWindowPosition(m_Data->m_Window, SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID), SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID));
336 if (!windowMoveSuccess) {
337 CORI_CORE_WARN_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to set window position to the center of the main screen. SDL_Error: {}", SDL_GetError());
338 }
339
340 success = SDL_SetWindowFullscreen(m_Data->m_Window, true);
341 if (!success) {
342 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Borderless Windowed'. SDL_Error: {}", SDL_GetError())));
343 }
344 success = SDL_SetWindowFullscreenMode(m_Data->m_Window, nullptr);
345 if (!success) {
346 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Borderless Windowed'. SDL_Error: {}", SDL_GetError())));
347 }
348
349 m_Data->m_CurrentWindowMode = mode;
350
351 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Window set to 'Borderless Windowed' mode.");
352
353 const std::filesystem::path savePath = FileSystem::PathManager::GetAliasedPath("USER_DATA") / "settings/window.bin";
354 std::filesystem::create_directories(savePath.parent_path());
355 const WindowSaveData data{ .m_Width = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width, .m_Height = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height, .m_RefreshRate = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_RefreshRate, .m_WindowMode = m_Data->m_CurrentWindowMode, .m_SDLModeIndex = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_SDLModeIndex, .m_ModeIndex = m_Data->m_CurrentScreenMode };
357
358 break;
359 }
361 {
362 const bool windowMoveSuccess = SDL_SetWindowPosition(m_Data->m_Window, SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID), SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID));
363 if (!windowMoveSuccess) {
364 CORI_CORE_WARN_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Failed to set window position to the center of the main screen. (This is expected on Wayland) SDL_Error: {}", SDL_GetError());
365 }
366
367 const SDL_DisplayMode* sdlMode = m_Data->m_SDLModes[m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_SDLModeIndex];
368 if (!sdlMode) {
369 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Exclusive Fullscreen'. SDL_Error: {}", SDL_GetError())));
370 }
371 success = SDL_SetWindowFullscreen(m_Data->m_Window, true);
372 if (!success) {
373 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Exclusive Fullscreen'. SDL_Error: {}", SDL_GetError())));
374 }
375 success = SDL_SetWindowFullscreenMode(m_Data->m_Window, sdlMode);
376 if (!success) {
377 return std::unexpected(CoriError(std::format("Failed to set window mode to 'Exclusive Fullscreen'. SDL_Error: {}", SDL_GetError())));
378 }
379
380 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::Core::Self, Logger::Tags::Core::Window }, "Window set to 'Exclusive Fullscreen' mode. Screen mode: (Width: {}, Height: {}, Refresh Rate: {})", sdlMode->w, sdlMode->h, sdlMode->refresh_rate);
381
382 m_Data->m_CurrentWindowMode = mode;
383
384 const std::filesystem::path savePath = FileSystem::PathManager::GetAliasedPath("USER_DATA") / "settings/window.bin";
385 std::filesystem::create_directories(savePath.parent_path());
386 const WindowSaveData data{ .m_Width = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width, .m_Height = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height, .m_RefreshRate = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_RefreshRate, .m_WindowMode = m_Data->m_CurrentWindowMode, .m_SDLModeIndex = m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_SDLModeIndex, .m_ModeIndex = m_Data->m_CurrentScreenMode };
388
389 break;
390 }
391 }
392
393 SDL_SyncWindow(m_Data->m_Window);
394
395 return {};
396 }
397 }
398}
#define CORI_CORE_DEBUG_TAGGED(...)
Definition Logger.hpp:1026
#define CORI_CORE_FATAL_TAGGED(...)
Definition Logger.hpp:1040
#define CORI_CORE_ASSERT(x,...)
Definition Logger.hpp:1029
#define CORI_CORE_ERROR_TAGGED(...)
Definition Logger.hpp:1039
#define CORI_CORE_VERIFY(x,...)
Definition Logger.hpp:1030
#define CORI_CORE_WARN_TAGGED(...)
Definition Logger.hpp:1038
#define CORI_CORE_INFO_TAGGED(...)
Definition Logger.hpp:1027
#define CORI_PROFILE_FUNCTION()
Definition Profiler.hpp:9
#define CORI_PROFILE_SCOPE(name)
Definition Profiler.hpp:10
Custom error class mainly used in std::expected.
Definition Error.hpp:27
This class manages everything that is connected with physical Window management, i might add multiwin...
Definition Window.hpp:43
int32_t GetHeight() const
Give the current window height.
Definition Window.cpp:232
std::expected< void, CoriError<> > SetScreenMode(const uint32_t modeIndex)
Changes the current ScreenMode.
Definition Window.cpp:274
const std::vector< ScreenMode > & GetScreenModes() const
Retrieves a list of all available ScreenMode.
Definition Window.cpp:270
uint32_t GetCurrentScreenMode() const
Retrieves the current screen mode index.
Definition Window.cpp:283
int32_t GetWidth() const
Give the current window width.
Definition Window.cpp:225
WindowMode GetWindowMode() const
Gets the current WindowMode;.
Definition Window.cpp:279
void SetVSync(const bool status)
Changes the VSync state.
Definition Window.cpp:245
bool IsVSync() const
Checks is VSynch is currently enabled.
Definition Window.cpp:257
std::expected< void, CoriError<> > SetWindowMode(WindowMode mode)
Changes the current WindowMode.
Definition Window.cpp:288
static std::expected< T, Core::CoriError<> > LoadAggregateStruct(const std::filesystem::path &file, const bool backupFallback=false)
Loads an aggregate struct from the file on the disk.
static void SaveAggregateStruct(const T &data, const std::filesystem::path &file, const bool safeMode=false)
Saves an instance of an aggregate struct onto the disk.
static std::filesystem::path GetAliasedPath(const std::string &alias)
Retries the full aliased path defined in fsgame.json.
static std::unique_ptr< RenderingContext > Create(GraphicsAPIs api)
Core systems of the engine are here.
std::function< void(Event &)> EventCallbackFn
Definition Event.hpp:112
CoriKeycode
This is a adaptation of SDL3 scancodes. Taken from 'SDL_scancode.h'.
enum Cori::Core::CoriMouseCode CoriMouseKeycode
An enum of all available mouse buttons.
@ Vulkan
I want to support vulkan, BUT later-later.
@ None
Invalid enumerator.
@ OpenGL
The only one available for now.
Global engine namespace.
std::vector< ScreenMode > m_ScreenModes
Definition Window.cpp:14
SDL_Window * m_Window
Definition Window.cpp:23
WindowMode m_CurrentWindowMode
Definition Window.cpp:16
uint32_t m_CurrentScreenMode
Definition Window.cpp:15
SDL_DisplayID m_PrimaryDisplayID
Definition Window.cpp:21
std::string m_WindowTitle
Definition Window.cpp:17
EventCallbackFn m_EventCallback
Definition Window.cpp:27
SDL_DisplayMode ** m_SDLModes
Definition Window.cpp:20
std::unique_ptr< Graphics::RenderingContext > m_Context
Definition Window.cpp:24
static constexpr char Window[]
Definition Logger.hpp:97
static constexpr char Self[]
Definition Logger.hpp:83