3#include <backends/imgui_impl_sdl3.h>
4#include <SDL3_image/SDL_image.h>
24 std::unique_ptr<Graphics::RenderingContext>
m_Context;
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));
39 Window::Window(std::string title,
const bool vsync) {
47 const SDL_DisplayID primaryDisplayID = SDL_GetPrimaryDisplay();
48 if (primaryDisplayID == 0) {
52 m_Data->m_PrimaryDisplayID = primaryDisplayID;
55 m_Data->m_SDLModes = SDL_GetFullscreenDisplayModes(m_Data->m_PrimaryDisplayID, &m_Data->m_DisplayModeCount);
57 CORI_CORE_VERIFY(m_Data->m_SDLModes,
"Failed to get screen modes, Window '{}' can not be created. SDL_Error: {}", title, SDL_GetError());
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);
64 ScreenMode mode = m_Data->m_ScreenModes[0];
67 std::filesystem::create_directories(savePath.parent_path());
69 bool configLoaded =
false;
71 if (std::filesystem::exists(savePath)) {
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;
90 m_Data->m_CurrentScreenMode = 0;
93 SDL_Rect displayBounds;
94 const bool success = SDL_GetDisplayBounds(m_Data->m_PrimaryDisplayID, &displayBounds);
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);
112 SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN,
true);
119 m_Data->m_Window = SDL_CreateWindowWithProperties(props);
121 SDL_DestroyProperties(props);
123 CORI_CORE_ASSERT(m_Data->m_Window,
"Failed to create Window '{}'. SDL_Error: {}", m_Data->m_WindowTitle, SDL_GetError());
126 SDL_Surface* logo = IMG_Load(logoPath.string().c_str());
131 SDL_SetWindowIcon(m_Data->m_Window, logo);
134 SDL_DestroySurface(logo);
136 SDL_SetWindowPosition(m_Data->m_Window, SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID), SDL_WINDOWPOS_CENTERED_DISPLAY(m_Data->m_PrimaryDisplayID));
138 m_Data->m_Context->Init(m_Data->m_Window);
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 };
154 void Window::OnUpdate() {
158 while (SDL_PollEvent(&e)) {
159 ImGui_ImplSDL3_ProcessEvent(&e);
163 case SDL_EVENT_WINDOW_RESIZED:
165 if (e.window.windowID != SDL_GetWindowID(m_Data->
m_Window)) {
174 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
176 WindowCloseEvent closeEvent;
180 case SDL_EVENT_KEY_DOWN:
182 KeyPressedEvent keyPressedEvent(
static_cast<CoriKeycode>(e.key.scancode), e.key.repeat);
183 m_Data->m_EventCallback(keyPressedEvent);
186 case SDL_EVENT_KEY_UP:
188 KeyReleasedEvent keyReleasedEvent(
static_cast<CoriKeycode>(e.key.scancode));
189 m_Data->m_EventCallback(keyReleasedEvent);
192 case SDL_EVENT_MOUSE_MOTION:
194 MouseMovedEvent mouseMovedEvent(
static_cast<int32_t
>(e.motion.x),
static_cast<int32_t
>(e.motion.y));
195 m_Data->m_EventCallback(mouseMovedEvent);
198 case SDL_EVENT_MOUSE_WHEEL:
200 MouseScrolledEvent mouseScrolledEvent(
static_cast<int16_t
>(e.wheel.x),
static_cast<int16_t
>(e.wheel.y));
201 m_Data->m_EventCallback(mouseScrolledEvent);
204 case SDL_EVENT_MOUSE_BUTTON_DOWN:
206 MouseButtonPressedEvent mouseButtonPressedEvent(
static_cast<CoriMouseKeycode>(e.button.button));
207 m_Data->m_EventCallback(mouseButtonPressedEvent);
210 case SDL_EVENT_MOUSE_BUTTON_UP:
212 MouseButtonReleasedEvent mouseButtonReleasedEvent(
static_cast<CoriMouseKeycode>(e.button.button));
213 m_Data->m_EventCallback(mouseButtonReleasedEvent);
221 m_Data->m_Context->SwapBuffers();
227 return m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Width;
229 return m_Data->m_ScreenModes[0].m_Width;
234 return m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_Height;
236 return m_Data->m_ScreenModes[0].m_Height;
247 SDL_GL_SetSwapInterval(0);
250 SDL_GL_SetSwapInterval(1);
253 m_Data->m_VSync = status;
258 return m_Data->m_VSync;
262 void* Window::GetNativeContext()
const {
263 return m_Data->
m_Context->GetNativeContext();
266 void* Window::GetNativeWindow()
const {
271 return m_Data->m_ScreenModes;
275 m_Data->m_CurrentScreenMode = modeIndex;
280 return m_Data->m_CurrentWindowMode;
284 return m_Data->m_CurrentScreenMode;
293 success = SDL_SetWindowFullscreen(m_Data->m_Window,
false);
295 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Windowed'. SDL_Error: {}", SDL_GetError())));
297 const bool borderAdded = SDL_SetWindowBordered(m_Data->m_Window,
true);
302 const SDL_DisplayMode* desktopMode = SDL_GetCurrentDisplayMode(m_Data->m_PrimaryDisplayID);
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);
307 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Windowed'. SDL_Error: {}", SDL_GetError())));
311 success = SDL_SetWindowSize(m_Data->m_Window, desktopMode->w, desktopMode->h);
313 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Windowed'. SDL_Error: {}", SDL_GetError())));
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) {
324 m_Data->m_CurrentWindowMode = mode;
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 };
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) {
340 success = SDL_SetWindowFullscreen(m_Data->m_Window,
true);
342 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Borderless Windowed'. SDL_Error: {}", SDL_GetError())));
344 success = SDL_SetWindowFullscreenMode(m_Data->m_Window,
nullptr);
346 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Borderless Windowed'. SDL_Error: {}", SDL_GetError())));
349 m_Data->m_CurrentWindowMode = mode;
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 };
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) {
367 const SDL_DisplayMode* sdlMode = m_Data->m_SDLModes[m_Data->m_ScreenModes[m_Data->m_CurrentScreenMode].m_SDLModeIndex];
369 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Exclusive Fullscreen'. SDL_Error: {}", SDL_GetError())));
371 success = SDL_SetWindowFullscreen(m_Data->m_Window,
true);
373 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Exclusive Fullscreen'. SDL_Error: {}", SDL_GetError())));
375 success = SDL_SetWindowFullscreenMode(m_Data->m_Window, sdlMode);
377 return std::unexpected(
CoriError(std::format(
"Failed to set window mode to 'Exclusive Fullscreen'. SDL_Error: {}", SDL_GetError())));
382 m_Data->m_CurrentWindowMode = mode;
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 };
393 SDL_SyncWindow(m_Data->m_Window);
#define CORI_CORE_DEBUG_TAGGED(...)
#define CORI_CORE_FATAL_TAGGED(...)
#define CORI_CORE_ASSERT(x,...)
#define CORI_CORE_ERROR_TAGGED(...)
#define CORI_CORE_VERIFY(x,...)
#define CORI_CORE_WARN_TAGGED(...)
#define CORI_CORE_INFO_TAGGED(...)
#define CORI_PROFILE_FUNCTION()
#define CORI_PROFILE_SCOPE(name)
Custom error class mainly used in std::expected.
This class manages everything that is connected with physical Window management, i might add multiwin...
int32_t GetHeight() const
Give the current window height.
std::expected< void, CoriError<> > SetScreenMode(const uint32_t modeIndex)
Changes the current ScreenMode.
const std::vector< ScreenMode > & GetScreenModes() const
Retrieves a list of all available ScreenMode.
uint32_t GetCurrentScreenMode() const
Retrieves the current screen mode index.
int32_t GetWidth() const
Give the current window width.
WindowMode GetWindowMode() const
Gets the current WindowMode;.
void SetVSync(const bool status)
Changes the VSync state.
bool IsVSync() const
Checks is VSynch is currently enabled.
std::expected< void, CoriError<> > SetWindowMode(WindowMode mode)
Changes the current WindowMode.
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
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.
std::vector< ScreenMode > m_ScreenModes
WindowMode m_CurrentWindowMode
uint32_t m_CurrentScreenMode
SDL_DisplayID m_PrimaryDisplayID
std::string m_WindowTitle
EventCallbackFn m_EventCallback
SDL_DisplayMode ** m_SDLModes
int32_t m_DisplayModeCount
std::unique_ptr< Graphics::RenderingContext > m_Context