9#include "absl/status/status.h"
10#include "absl/strings/str_format.h"
14#include "imgui/backends/imgui_impl_sdl2.h"
15#include "imgui/backends/imgui_impl_sdlrenderer2.h"
16#include "imgui/imgui.h"
30#define g_window_is_resizing yaze::core::g_window_is_resizing
40 LOG_WARN(
"SDL2WindowBackend",
"Already initialized, shutting down first");
45 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) {
46 return absl::InternalError(
47 absl::StrFormat(
"SDL_Init failed: %s", SDL_GetError()));
51 int screen_width = config.
width;
52 int screen_height = config.
height;
54 if (screen_width == 0 || screen_height == 0) {
56 SDL_DisplayMode display_mode;
57 if (SDL_GetCurrentDisplayMode(0, &display_mode) == 0) {
58 screen_width =
static_cast<int>(display_mode.w * config.
display_scale);
59 screen_height =
static_cast<int>(display_mode.h * config.
display_scale);
65 "Failed to get display mode, using defaults: %dx%d",
66 screen_width, screen_height);
73 flags |= SDL_WINDOW_RESIZABLE;
76 flags |= SDL_WINDOW_MAXIMIZED;
79 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
82 flags |= SDL_WINDOW_ALLOW_HIGHDPI;
85 flags |= SDL_WINDOW_HIDDEN;
89 window_ = std::unique_ptr<SDL_Window, util::SDL_Deleter>(
90 SDL_CreateWindow(config.
title.c_str(), SDL_WINDOWPOS_UNDEFINED,
91 SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height,
97 return absl::InternalError(
98 absl::StrFormat(
"SDL_CreateWindow failed: %s", SDL_GetError()));
102 const int audio_frequency = 48000;
103 const size_t buffer_size = (audio_frequency / 50) * 2;
104 audio_buffer_ = std::shared_ptr<int16_t>(
new int16_t[buffer_size],
105 std::default_delete<int16_t[]>());
107 LOG_INFO(
"SDL2WindowBackend",
"Initialized: %dx%d, audio buffer: %zu samples",
108 screen_width, screen_height, buffer_size);
112 return absl::OkStatus();
117 return absl::OkStatus();
133 LOG_INFO(
"SDL2WindowBackend",
"Shutting down graphics arena...");
138 LOG_INFO(
"SDL2WindowBackend",
"Destroying window...");
143 LOG_INFO(
"SDL2WindowBackend",
"Shutting down SDL...");
147 LOG_INFO(
"SDL2WindowBackend",
"Shutdown complete");
148 return absl::OkStatus();
153 if (SDL_PollEvent(&sdl_event)) {
156 ImGui_ImplSDL2_ProcessEvent(&sdl_event);
170 ImGui_ImplSDL2_ProcessEvent(
static_cast<SDL_Event*
>(native_event));
178 switch (sdl_event.type) {
186 event.key_code = sdl_event.key.keysym.sym;
187 event.scan_code = sdl_event.key.keysym.scancode;
197 event.key_code = sdl_event.key.keysym.sym;
198 event.scan_code = sdl_event.key.keysym.scancode;
206 case SDL_MOUSEMOTION:
208 event.mouse_x =
static_cast<float>(sdl_event.motion.x);
209 event.mouse_y =
static_cast<float>(sdl_event.motion.y);
212 case SDL_MOUSEBUTTONDOWN:
214 event.mouse_x =
static_cast<float>(sdl_event.button.x);
215 event.mouse_y =
static_cast<float>(sdl_event.button.y);
216 event.mouse_button = sdl_event.button.button;
219 case SDL_MOUSEBUTTONUP:
221 event.mouse_x =
static_cast<float>(sdl_event.button.x);
222 event.mouse_y =
static_cast<float>(sdl_event.button.y);
223 event.mouse_button = sdl_event.button.button;
228 event.wheel_x =
static_cast<float>(sdl_event.wheel.x);
229 event.wheel_y =
static_cast<float>(sdl_event.wheel.y);
234 if (sdl_event.drop.file) {
235 event.dropped_file = sdl_event.drop.file;
236 SDL_free(sdl_event.drop.file);
240 case SDL_WINDOWEVENT:
241 switch (sdl_event.window.event) {
242 case SDL_WINDOWEVENT_CLOSE:
247 case SDL_WINDOWEVENT_SIZE_CHANGED:
248 case SDL_WINDOWEVENT_RESIZED:
250 event.window_width = sdl_event.window.data1;
251 event.window_height = sdl_event.window.data2;
256 case SDL_WINDOWEVENT_MINIMIZED:
262 case SDL_WINDOWEVENT_MAXIMIZED:
266 case SDL_WINDOWEVENT_RESTORED:
272 case SDL_WINDOWEVENT_SHOWN:
278 case SDL_WINDOWEVENT_HIDDEN:
284 case SDL_WINDOWEVENT_EXPOSED:
290 case SDL_WINDOWEVENT_FOCUS_GAINED:
294 case SDL_WINDOWEVENT_FOCUS_LOST:
305 SDL_Keymod mod = SDL_GetModState();
318 Uint32 flags = SDL_GetWindowFlags(
window_.get());
319 status.
is_minimized = (flags & SDL_WINDOW_MINIMIZED) != 0;
320 status.
is_maximized = (flags & SDL_WINDOW_MAXIMIZED) != 0;
322 (flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0;
323 status.
is_focused = (flags & SDL_WINDOW_INPUT_FOCUS) != 0;
333 SDL_GetWindowSize(
window_.get(), width, height);
344 SDL_SetWindowSize(
window_.get(), width, height);
350 const char* title = SDL_GetWindowTitle(
window_.get());
351 return title ? title :
"";
358 SDL_SetWindowTitle(
window_.get(), title.c_str());
389 return absl::OkStatus();
393 return absl::InvalidArgumentError(
"Renderer is null");
396 IMGUI_CHECKVERSION();
397 ImGui::CreateContext();
399 ImGuiIO& io = ImGui::GetIO();
400 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
401 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
408 io.ConfigMacOSXBehaviors =
true;
409 LOG_INFO(
"SDL2WindowBackend",
"Enabled ConfigMacOSXBehaviors for macOS");
413 static std::string ini_path_str;
414 if (ini_path_str.empty()) {
415 ini_path_str = ini_path->string();
417 io.IniFilename = ini_path_str.c_str();
419 io.IniFilename =
nullptr;
420 LOG_WARN(
"SDL2WindowBackend",
"Failed to resolve ImGui ini path: %s",
421 ini_path.status().ToString().c_str());
425 SDL_Renderer* sdl_renderer =
429 return absl::InternalError(
"Failed to get SDL renderer from IRenderer");
432 if (!ImGui_ImplSDL2_InitForSDLRenderer(
window_.get(), sdl_renderer)) {
433 return absl::InternalError(
"ImGui_ImplSDL2_InitForSDLRenderer failed");
436 if (!ImGui_ImplSDLRenderer2_Init(sdl_renderer)) {
437 ImGui_ImplSDL2_Shutdown();
438 return absl::InternalError(
"ImGui_ImplSDLRenderer2_Init failed");
448 LOG_INFO(
"SDL2WindowBackend",
"ImGui initialized successfully");
449 return absl::OkStatus();
457 LOG_INFO(
"SDL2WindowBackend",
"Shutting down ImGui implementations...");
458 ImGui_ImplSDLRenderer2_Shutdown();
459 ImGui_ImplSDL2_Shutdown();
461 LOG_INFO(
"SDL2WindowBackend",
"Destroying ImGui context...");
462 ImGui::DestroyContext();
472 ImGui_ImplSDLRenderer2_NewFrame();
473 ImGui_ImplSDL2_NewFrame();
488 SDL_Renderer* sdl_renderer =
491 ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer);
496 ImGuiIO& io = ImGui::GetIO();
497 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
498 ImGui::UpdatePlatformWindows();
499 ImGui::RenderPlatformWindowsDefault();
Defines an abstract interface for all rendering operations.
virtual bool Initialize(SDL_Window *window)=0
Initializes the renderer with a given window.
virtual void * GetBackendRenderer()=0
Provides an escape hatch to get the underlying, concrete renderer object.
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
bool g_window_is_resizing
absl::Status LoadPackageFonts()
#define g_window_is_resizing
SDL2/SDL3 compatibility layer.
#define RETURN_IF_ERROR(expr)
Deleter for SDL_Window and SDL_Renderer.