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"
29#define g_window_is_resizing yaze::core::g_window_is_resizing
39 LOG_WARN(
"SDL2WindowBackend",
"Already initialized, shutting down first");
44 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) {
45 return absl::InternalError(
46 absl::StrFormat(
"SDL_Init failed: %s", SDL_GetError()));
50 int screen_width = config.
width;
51 int screen_height = config.
height;
53 if (screen_width == 0 || screen_height == 0) {
55 SDL_DisplayMode display_mode;
56 if (SDL_GetCurrentDisplayMode(0, &display_mode) == 0) {
57 screen_width =
static_cast<int>(display_mode.w * config.
display_scale);
58 screen_height =
static_cast<int>(display_mode.h * config.
display_scale);
64 "Failed to get display mode, using defaults: %dx%d",
65 screen_width, screen_height);
72 flags |= SDL_WINDOW_RESIZABLE;
75 flags |= SDL_WINDOW_MAXIMIZED;
78 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
81 flags |= SDL_WINDOW_ALLOW_HIGHDPI;
85 window_ = std::unique_ptr<SDL_Window, util::SDL_Deleter>(
86 SDL_CreateWindow(config.
title.c_str(), SDL_WINDOWPOS_UNDEFINED,
87 SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height,
93 return absl::InternalError(
94 absl::StrFormat(
"SDL_CreateWindow failed: %s", SDL_GetError()));
98 const int audio_frequency = 48000;
99 const size_t buffer_size = (audio_frequency / 50) * 2;
100 audio_buffer_ = std::shared_ptr<int16_t>(
new int16_t[buffer_size],
101 std::default_delete<int16_t[]>());
103 LOG_INFO(
"SDL2WindowBackend",
"Initialized: %dx%d, audio buffer: %zu samples",
104 screen_width, screen_height, buffer_size);
108 return absl::OkStatus();
113 return absl::OkStatus();
129 LOG_INFO(
"SDL2WindowBackend",
"Shutting down graphics arena...");
134 LOG_INFO(
"SDL2WindowBackend",
"Destroying window...");
139 LOG_INFO(
"SDL2WindowBackend",
"Shutting down SDL...");
143 LOG_INFO(
"SDL2WindowBackend",
"Shutdown complete");
144 return absl::OkStatus();
149 if (SDL_PollEvent(&sdl_event)) {
152 ImGui_ImplSDL2_ProcessEvent(&sdl_event);
166 ImGui_ImplSDL2_ProcessEvent(
static_cast<SDL_Event*
>(native_event));
174 switch (sdl_event.type) {
182 event.key_code = sdl_event.key.keysym.sym;
183 event.scan_code = sdl_event.key.keysym.scancode;
193 event.key_code = sdl_event.key.keysym.sym;
194 event.scan_code = sdl_event.key.keysym.scancode;
202 case SDL_MOUSEMOTION:
204 event.mouse_x =
static_cast<float>(sdl_event.motion.x);
205 event.mouse_y =
static_cast<float>(sdl_event.motion.y);
208 case SDL_MOUSEBUTTONDOWN:
210 event.mouse_x =
static_cast<float>(sdl_event.button.x);
211 event.mouse_y =
static_cast<float>(sdl_event.button.y);
212 event.mouse_button = sdl_event.button.button;
215 case SDL_MOUSEBUTTONUP:
217 event.mouse_x =
static_cast<float>(sdl_event.button.x);
218 event.mouse_y =
static_cast<float>(sdl_event.button.y);
219 event.mouse_button = sdl_event.button.button;
224 event.wheel_x =
static_cast<float>(sdl_event.wheel.x);
225 event.wheel_y =
static_cast<float>(sdl_event.wheel.y);
230 if (sdl_event.drop.file) {
231 event.dropped_file = sdl_event.drop.file;
232 SDL_free(sdl_event.drop.file);
236 case SDL_WINDOWEVENT:
237 switch (sdl_event.window.event) {
238 case SDL_WINDOWEVENT_CLOSE:
243 case SDL_WINDOWEVENT_SIZE_CHANGED:
244 case SDL_WINDOWEVENT_RESIZED:
246 event.window_width = sdl_event.window.data1;
247 event.window_height = sdl_event.window.data2;
252 case SDL_WINDOWEVENT_MINIMIZED:
258 case SDL_WINDOWEVENT_MAXIMIZED:
262 case SDL_WINDOWEVENT_RESTORED:
268 case SDL_WINDOWEVENT_SHOWN:
274 case SDL_WINDOWEVENT_HIDDEN:
280 case SDL_WINDOWEVENT_EXPOSED:
286 case SDL_WINDOWEVENT_FOCUS_GAINED:
290 case SDL_WINDOWEVENT_FOCUS_LOST:
301 SDL_Keymod mod = SDL_GetModState();
314 Uint32 flags = SDL_GetWindowFlags(
window_.get());
315 status.
is_minimized = (flags & SDL_WINDOW_MINIMIZED) != 0;
316 status.
is_maximized = (flags & SDL_WINDOW_MAXIMIZED) != 0;
318 (flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0;
319 status.
is_focused = (flags & SDL_WINDOW_INPUT_FOCUS) != 0;
329 SDL_GetWindowSize(
window_.get(), width, height);
340 SDL_SetWindowSize(
window_.get(), width, height);
346 const char* title = SDL_GetWindowTitle(
window_.get());
347 return title ? title :
"";
354 SDL_SetWindowTitle(
window_.get(), title.c_str());
373 return absl::OkStatus();
377 return absl::InvalidArgumentError(
"Renderer is null");
380 IMGUI_CHECKVERSION();
381 ImGui::CreateContext();
383 ImGuiIO& io = ImGui::GetIO();
384 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
385 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
392 io.ConfigMacOSXBehaviors =
true;
393 LOG_INFO(
"SDL2WindowBackend",
"Enabled ConfigMacOSXBehaviors for macOS");
397 SDL_Renderer* sdl_renderer =
401 return absl::InternalError(
"Failed to get SDL renderer from IRenderer");
404 if (!ImGui_ImplSDL2_InitForSDLRenderer(
window_.get(), sdl_renderer)) {
405 return absl::InternalError(
"ImGui_ImplSDL2_InitForSDLRenderer failed");
408 if (!ImGui_ImplSDLRenderer2_Init(sdl_renderer)) {
409 ImGui_ImplSDL2_Shutdown();
410 return absl::InternalError(
"ImGui_ImplSDLRenderer2_Init failed");
420 LOG_INFO(
"SDL2WindowBackend",
"ImGui initialized successfully");
421 return absl::OkStatus();
429 LOG_INFO(
"SDL2WindowBackend",
"Shutting down ImGui implementations...");
430 ImGui_ImplSDLRenderer2_Shutdown();
431 ImGui_ImplSDL2_Shutdown();
433 LOG_INFO(
"SDL2WindowBackend",
"Destroying ImGui context...");
434 ImGui::DestroyContext();
444 ImGui_ImplSDLRenderer2_NewFrame();
445 ImGui_ImplSDL2_NewFrame();
460 SDL_Renderer* sdl_renderer =
463 ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer);
468 ImGuiIO& io = ImGui::GetIO();
469 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
470 ImGui::UpdatePlatformWindows();
471 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.