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 |
46 SDL_INIT_GAMECONTROLLER) != 0) {
47 return absl::InternalError(
48 absl::StrFormat(
"SDL_Init failed: %s", SDL_GetError()));
52 int screen_width = config.
width;
53 int screen_height = config.
height;
55 if (screen_width == 0 || screen_height == 0) {
57 SDL_DisplayMode display_mode;
58 if (SDL_GetCurrentDisplayMode(0, &display_mode) == 0) {
59 screen_width =
static_cast<int>(display_mode.w * config.
display_scale);
60 screen_height =
static_cast<int>(display_mode.h * config.
display_scale);
66 "Failed to get display mode, using defaults: %dx%d",
67 screen_width, screen_height);
74 flags |= SDL_WINDOW_RESIZABLE;
77 flags |= SDL_WINDOW_MAXIMIZED;
80 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
83 flags |= SDL_WINDOW_ALLOW_HIGHDPI;
86 flags |= SDL_WINDOW_HIDDEN;
90 window_ = std::unique_ptr<SDL_Window, util::SDL_Deleter>(
91 SDL_CreateWindow(config.
title.c_str(), SDL_WINDOWPOS_UNDEFINED,
92 SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height,
98 return absl::InternalError(
99 absl::StrFormat(
"SDL_CreateWindow failed: %s", SDL_GetError()));
103 const int audio_frequency = 48000;
104 const size_t buffer_size = (audio_frequency / 50) * 2;
105 audio_buffer_ = std::shared_ptr<int16_t>(
new int16_t[buffer_size],
106 std::default_delete<int16_t[]>());
108 LOG_INFO(
"SDL2WindowBackend",
"Initialized: %dx%d, audio buffer: %zu samples",
109 screen_width, screen_height, buffer_size);
113 return absl::OkStatus();
118 return absl::OkStatus();
134 LOG_INFO(
"SDL2WindowBackend",
"Shutting down graphics arena...");
139 LOG_INFO(
"SDL2WindowBackend",
"Destroying window...");
144 LOG_INFO(
"SDL2WindowBackend",
"Shutting down SDL...");
148 LOG_INFO(
"SDL2WindowBackend",
"Shutdown complete");
149 return absl::OkStatus();
154 if (SDL_PollEvent(&sdl_event)) {
157 ImGui_ImplSDL2_ProcessEvent(&sdl_event);
171 ImGui_ImplSDL2_ProcessEvent(
static_cast<SDL_Event*
>(native_event));
179 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:
246 case SDL_WINDOWEVENT_SIZE_CHANGED:
247 case SDL_WINDOWEVENT_RESIZED:
249 event.window_width = sdl_event.window.data1;
250 event.window_height = sdl_event.window.data2;
255 case SDL_WINDOWEVENT_MINIMIZED:
261 case SDL_WINDOWEVENT_MAXIMIZED:
265 case SDL_WINDOWEVENT_RESTORED:
271 case SDL_WINDOWEVENT_SHOWN:
277 case SDL_WINDOWEVENT_HIDDEN:
283 case SDL_WINDOWEVENT_EXPOSED:
289 case SDL_WINDOWEVENT_FOCUS_GAINED:
293 case SDL_WINDOWEVENT_FOCUS_LOST:
304 SDL_Keymod mod = SDL_GetModState();
317 Uint32 flags = SDL_GetWindowFlags(
window_.get());
318 status.
is_minimized = (flags & SDL_WINDOW_MINIMIZED) != 0;
319 status.
is_maximized = (flags & SDL_WINDOW_MAXIMIZED) != 0;
321 (flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0;
322 status.
is_focused = (flags & SDL_WINDOW_INPUT_FOCUS) != 0;
332 SDL_GetWindowSize(
window_.get(), width, height);
343 SDL_SetWindowSize(
window_.get(), width, height);
349 const char* title = SDL_GetWindowTitle(
window_.get());
350 return title ? title :
"";
357 SDL_SetWindowTitle(
window_.get(), title.c_str());
388 return absl::OkStatus();
392 return absl::InvalidArgumentError(
"Renderer is null");
395 IMGUI_CHECKVERSION();
396 ImGui::CreateContext();
398 ImGuiIO& io = ImGui::GetIO();
399 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
400 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
407 io.ConfigMacOSXBehaviors =
true;
408 LOG_INFO(
"SDL2WindowBackend",
"Enabled ConfigMacOSXBehaviors for macOS");
412 static std::string ini_path_str;
413 if (ini_path_str.empty()) {
414 ini_path_str = ini_path->string();
416 io.IniFilename = ini_path_str.c_str();
418 io.IniFilename =
nullptr;
419 LOG_WARN(
"SDL2WindowBackend",
"Failed to resolve ImGui ini path: %s",
420 ini_path.status().ToString().c_str());
424 SDL_Renderer* sdl_renderer =
428 return absl::InternalError(
"Failed to get SDL renderer from IRenderer");
431 if (!ImGui_ImplSDL2_InitForSDLRenderer(
window_.get(), sdl_renderer)) {
432 return absl::InternalError(
"ImGui_ImplSDL2_InitForSDLRenderer failed");
435 if (!ImGui_ImplSDLRenderer2_Init(sdl_renderer)) {
436 ImGui_ImplSDL2_Shutdown();
437 return absl::InternalError(
"ImGui_ImplSDLRenderer2_Init failed");
447 LOG_INFO(
"SDL2WindowBackend",
"ImGui initialized successfully");
448 return absl::OkStatus();
456 LOG_INFO(
"SDL2WindowBackend",
"Shutting down ImGui implementations...");
457 ImGui_ImplSDLRenderer2_Shutdown();
458 ImGui_ImplSDL2_Shutdown();
460 LOG_INFO(
"SDL2WindowBackend",
"Destroying ImGui context...");
461 ImGui::DestroyContext();
471 ImGui_ImplSDLRenderer2_NewFrame();
472 ImGui_ImplSDL2_NewFrame();
487 SDL_Renderer* sdl_renderer =
490 ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer);
495 ImGuiIO& io = ImGui::GetIO();
496 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
497 ImGui::UpdatePlatformWindows();
498 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.