yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
window.cc
Go to the documentation of this file.
2
3#include <string>
4
5#include "absl/status/status.h"
6#include "absl/strings/str_format.h"
11#include "imgui/imgui.h"
12#include "util/log.h"
13#include "util/platform_paths.h"
14#include "util/sdl_deleter.h"
15
16#ifndef YAZE_USE_SDL3
17#include "imgui/backends/imgui_impl_sdl2.h"
18#include "imgui/backends/imgui_impl_sdlrenderer2.h"
19#endif
20
21namespace yaze {
22namespace core {
23
24// Global flag for window resize state (used by emulator to pause)
25bool g_window_is_resizing = false;
26
27absl::Status CreateWindow(Window& window, gfx::IRenderer* renderer, int flags) {
28#ifdef YAZE_USE_SDL3
29 return absl::FailedPreconditionError(
30 "Legacy SDL2 window path is unavailable when building with SDL3");
31#else
32 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) {
33 return absl::InternalError(
34 absl::StrFormat("SDL_Init: %s\n", SDL_GetError()));
35 }
36
37 SDL_DisplayMode display_mode;
38 SDL_GetCurrentDisplayMode(0, &display_mode);
39 int screen_width = display_mode.w * 0.8;
40 int screen_height = display_mode.h * 0.8;
41
42 window.window_ = std::unique_ptr<SDL_Window, util::SDL_Deleter>(
43 SDL_CreateWindow("Yet Another Zelda3 Editor", SDL_WINDOWPOS_UNDEFINED,
44 SDL_WINDOWPOS_UNDEFINED, screen_width, screen_height,
45 flags),
47 if (window.window_ == nullptr) {
48 return absl::InternalError(
49 absl::StrFormat("SDL_CreateWindow: %s\n", SDL_GetError()));
50 }
51
52 // Only initialize renderer if one is provided and not already initialized
53 if (renderer && !renderer->GetBackendRenderer()) {
54 if (!renderer->Initialize(window.window_.get())) {
55 return absl::InternalError("Failed to initialize renderer");
56 }
57 }
58
59 IMGUI_CHECKVERSION();
60 ImGui::CreateContext();
61 ImGuiIO& io = ImGui::GetIO();
63 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
64 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
65
66 // Ensure macOS-style behavior (Cmd acts as Ctrl for shortcuts)
67#ifdef __APPLE__
68 io.ConfigMacOSXBehaviors = true;
69#endif
70
71 if (auto ini_path = util::PlatformPaths::GetImGuiIniPath(); ini_path.ok()) {
72 static std::string ini_path_str;
73 if (ini_path_str.empty()) {
74 ini_path_str = ini_path->string();
75 }
76 io.IniFilename = ini_path_str.c_str();
77 } else {
78 io.IniFilename = nullptr;
79 LOG_WARN("Window", "Failed to resolve ImGui ini path: %s",
80 ini_path.status().ToString().c_str());
81 }
82
83 // Initialize ImGuiTestEngine after ImGui context is created
84#if defined(YAZE_ENABLE_IMGUI_TEST_ENGINE) && YAZE_ENABLE_IMGUI_TEST_ENGINE
86#endif
87
88 // Initialize ImGui backends if renderer is provided
89 if (renderer) {
90 SDL_Renderer* sdl_renderer =
91 static_cast<SDL_Renderer*>(renderer->GetBackendRenderer());
92 ImGui_ImplSDL2_InitForSDLRenderer(window.window_.get(), sdl_renderer);
93 ImGui_ImplSDLRenderer2_Init(sdl_renderer);
94 }
95
97
98 // Apply original YAZE colors as fallback, then try to load theme system
100
101 // Audio is now handled by IAudioBackend in Emulator class
102 // Keep legacy buffer allocation for backwards compatibility
103 if (window.audio_device_ == 0) {
104 const int audio_frequency = 48000;
105 const size_t buffer_size =
106 (audio_frequency / 50) * 2; // 1920 int16_t for stereo PAL
107
108 // CRITICAL FIX: Allocate buffer as ARRAY, not single value
109 // Use new[] with shared_ptr custom deleter for proper array allocation
110 window.audio_buffer_ = std::shared_ptr<int16_t>(
111 new int16_t[buffer_size], std::default_delete<int16_t[]>());
112
113 // Note: Actual audio device is created by Emulator's IAudioBackend
114 // This maintains compatibility with existing code paths
115 LOG_INFO(
116 "Window",
117 "Audio buffer allocated: %zu int16_t samples (backend in Emulator)",
118 buffer_size);
119 }
120
121 return absl::OkStatus();
122#endif // YAZE_USE_SDL3
123}
124
125absl::Status ShutdownWindow(Window& window) {
126#ifdef YAZE_USE_SDL3
127 return absl::FailedPreconditionError(
128 "Legacy SDL2 window path is unavailable when building with SDL3");
129#else
130 SDL_PauseAudioDevice(window.audio_device_, 1);
131 SDL_CloseAudioDevice(window.audio_device_);
132
133 // Stop test engine WHILE ImGui context is still valid
134#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
136#endif
137
138 // TODO: BAD FIX, SLOW SHUTDOWN TAKES TOO LONG NOW
139 // CRITICAL FIX: Shutdown graphics arena FIRST
140 // This ensures all textures are destroyed while renderer is still valid
141 LOG_INFO("Window", "Shutting down graphics arena...");
143
144 // Shutdown ImGui implementations (after Arena but before context)
145 LOG_INFO("Window", "Shutting down ImGui implementations...");
146 ImGui_ImplSDL2_Shutdown();
148
149 // Destroy ImGui context
150 LOG_INFO("Window", "Destroying ImGui context...");
151 ImGui::DestroyContext();
152
153 // NOW destroy test engine context (after ImGui context is destroyed)
154#ifdef YAZE_ENABLE_IMGUI_TEST_ENGINE
156#endif
157
158 // Finally destroy window
159 LOG_INFO("Window", "Destroying window...");
160 SDL_DestroyWindow(window.window_.get());
161
162 LOG_INFO("Window", "Shutting down SDL...");
163 SDL_Quit();
164
165 LOG_INFO("Window", "Shutdown complete");
166 return absl::OkStatus();
167#endif // YAZE_USE_SDL3
168}
169
170absl::Status HandleEvents(Window& window) {
171#ifdef YAZE_USE_SDL3
172 return absl::FailedPreconditionError(
173 "Legacy SDL2 window path is unavailable when building with SDL3");
174#else
175 SDL_Event event;
176 ImGuiIO& io = ImGui::GetIO();
177
178 // Protect SDL_PollEvent from crashing the app
179 // macOS NSPersistentUIManager corruption can crash during event polling
180 while (SDL_PollEvent(&event)) {
181 ImGui_ImplSDL2_ProcessEvent(&event);
182 switch (event.type) {
183 // Note: Keyboard modifiers are handled by ImGui_ImplSDL2_ProcessEvent
184 // which respects ConfigMacOSXBehaviors for Cmd/Ctrl swapping on macOS.
185 // Do NOT manually override io.KeyCtrl/KeySuper here.
186 case SDL_WINDOWEVENT:
187 switch (event.window.event) {
188 case SDL_WINDOWEVENT_CLOSE:
189 window.active_ = false;
190 break;
191 case SDL_WINDOWEVENT_SIZE_CHANGED:
192 case SDL_WINDOWEVENT_RESIZED:
193 // Update display size for both resize and size_changed events
194 io.DisplaySize.x = static_cast<float>(event.window.data1);
195 io.DisplaySize.y = static_cast<float>(event.window.data2);
197 break;
198 case SDL_WINDOWEVENT_MINIMIZED:
199 case SDL_WINDOWEVENT_HIDDEN:
200 // Window is minimized/hidden
201 g_window_is_resizing = false;
202 break;
203 case SDL_WINDOWEVENT_RESTORED:
204 case SDL_WINDOWEVENT_SHOWN:
205 case SDL_WINDOWEVENT_EXPOSED:
206 // Window is restored - clear resize flag
207 g_window_is_resizing = false;
208 break;
209 }
210 break;
211 }
212 }
213 int mouseX;
214 int mouseY;
215 const int buttons = SDL_GetMouseState(&mouseX, &mouseY);
216
217 io.DeltaTime = 1.0f / 60.0f;
218 io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
219 io.MouseDown[0] = buttons & SDL_BUTTON(SDL_BUTTON_LEFT);
220 io.MouseDown[1] = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT);
221 io.MouseDown[2] = buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE);
222
223 int wheel = 0;
224 io.MouseWheel = static_cast<float>(wheel);
225 return absl::OkStatus();
226#endif // YAZE_USE_SDL3
227}
228
229} // namespace core
230} // namespace yaze
void Shutdown()
Definition arena.cc:489
static Arena & Get()
Definition arena.cc:24
Defines an abstract interface for all rendering operations.
Definition irenderer.h:60
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.
static TestManager & Get()
static absl::StatusOr< std::filesystem::path > GetImGuiIniPath()
Get the ImGui ini path for YAZE.
bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer *renderer)
void ImGui_ImplSDLRenderer2_Shutdown()
#define LOG_WARN(category, format,...)
Definition log.h:138
#define LOG_INFO(category, format,...)
Definition log.h:136
absl::Status ShutdownWindow(Window &window)
Definition window.cc:125
absl::Status HandleEvents(Window &window)
Definition window.cc:170
absl::Status CreateWindow(Window &window, gfx::IRenderer *renderer, int flags)
Definition window.cc:27
void ColorsYaze()
Definition style.cc:33
void ConfigureImGuiDiagnostics(ImGuiIO &io, ImGuiDiagnosticsBuild build)
Set Dear ImGui's error-recovery and ID-conflict options.
absl::Status LoadPackageFonts()
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
std::shared_ptr< SDL_Window > window_
Definition window.h:21
std::shared_ptr< int16_t > audio_buffer_
Definition window.h:23
SDL_AudioDeviceID audio_device_
Definition window.h:22
Deleter for SDL_Window and SDL_Renderer.
Definition sdl_deleter.h:19