backend-infra-engineer: Post v0.3.9-hotfix7 snapshot (build cleanup)
This commit is contained in:
@@ -6,32 +6,49 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/editor/editor_manager.h"
|
||||
#include "app/gfx/backend/renderer_factory.h" // Use renderer factory for SDL2/SDL3 selection
|
||||
#include "app/gfx/resource/arena.h" // Add include for Arena
|
||||
#include "app/gfx/backend/renderer_factory.h"
|
||||
#include "app/gfx/resource/arena.h"
|
||||
#include "app/gui/automation/widget_id_registry.h"
|
||||
#include "app/gui/core/background_renderer.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "app/emu/emulator.h"
|
||||
#include "app/platform/iwindow.h"
|
||||
#include "app/platform/timing.h"
|
||||
#include "app/platform/window.h"
|
||||
#include "imgui/backends/imgui_impl_sdl2.h"
|
||||
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
|
||||
#include "app/service/screenshot_utils.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
|
||||
absl::Status Controller::OnEntry(std::string filename) {
|
||||
// Create renderer FIRST (uses factory for SDL2/SDL3 selection)
|
||||
renderer_ = gfx::RendererFactory::Create();
|
||||
// Create window backend using factory (auto-selects SDL2 or SDL3)
|
||||
window_backend_ = platform::WindowBackendFactory::Create(
|
||||
platform::WindowBackendFactory::GetDefaultType());
|
||||
|
||||
// Call CreateWindow with our renderer
|
||||
RETURN_IF_ERROR(CreateWindow(window_, renderer_.get(), SDL_WINDOW_RESIZABLE));
|
||||
platform::WindowConfig config;
|
||||
config.title = "Yet Another Zelda3 Editor";
|
||||
config.resizable = true;
|
||||
config.high_dpi = false; // Disabled to match legacy behavior (SDL_WINDOW_RESIZABLE only)
|
||||
|
||||
RETURN_IF_ERROR(window_backend_->Initialize(config));
|
||||
|
||||
// Create renderer via factory (auto-selects SDL2 or SDL3)
|
||||
renderer_ = gfx::RendererFactory::Create();
|
||||
if (!window_backend_->InitializeRenderer(renderer_.get())) {
|
||||
return absl::InternalError("Failed to initialize renderer");
|
||||
}
|
||||
|
||||
// Initialize ImGui via backend (handles SDL2/SDL3 automatically)
|
||||
RETURN_IF_ERROR(window_backend_->InitializeImGui(renderer_.get()));
|
||||
|
||||
// Initialize the graphics Arena with the renderer
|
||||
gfx::Arena::Get().Initialize(renderer_.get());
|
||||
|
||||
// Set up audio for emulator
|
||||
editor_manager_.emulator().set_audio_buffer(window_.audio_buffer_.get());
|
||||
editor_manager_.emulator().set_audio_device_id(window_.audio_device_);
|
||||
// Set up audio for emulator (using backend's audio resources)
|
||||
auto audio_buffer = window_backend_->GetAudioBuffer();
|
||||
if (audio_buffer) {
|
||||
editor_manager_.emulator().set_audio_buffer(audio_buffer.get());
|
||||
}
|
||||
editor_manager_.emulator().set_audio_device_id(window_backend_->GetAudioDevice());
|
||||
|
||||
// Initialize editor manager with renderer
|
||||
editor_manager_.Initialize(renderer_.get(), filename);
|
||||
@@ -41,36 +58,82 @@ absl::Status Controller::OnEntry(std::string filename) {
|
||||
}
|
||||
|
||||
void Controller::SetStartupEditor(const std::string& editor_name,
|
||||
const std::string& cards) {
|
||||
// Process command-line flags for editor and cards
|
||||
// Example: --editor=Dungeon --cards="Rooms List,Room 0,Room 105"
|
||||
const std::string& panels) {
|
||||
// Process command-line flags for editor and panels
|
||||
// Example: --editor=Dungeon --open_panels="dungeon.room_list,Room 0"
|
||||
if (!editor_name.empty()) {
|
||||
editor_manager_.OpenEditorAndCardsFromFlags(editor_name, cards);
|
||||
editor_manager_.OpenEditorAndPanelsFromFlags(editor_name, panels);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::OnInput() {
|
||||
PRINT_IF_ERROR(HandleEvents(window_));
|
||||
if (!window_backend_) return;
|
||||
|
||||
platform::WindowEvent event;
|
||||
while (window_backend_->PollEvent(event)) {
|
||||
switch (event.type) {
|
||||
case platform::WindowEventType::Quit:
|
||||
case platform::WindowEventType::Close:
|
||||
active_ = false;
|
||||
break;
|
||||
default:
|
||||
// Other events are handled by ImGui via ProcessNativeEvent
|
||||
// which is called inside PollEvent
|
||||
break;
|
||||
}
|
||||
|
||||
// Forward native SDL events to emulator input for event-based paths
|
||||
if (event.has_native_event) {
|
||||
editor_manager_.emulator().input_manager().ProcessEvent(
|
||||
static_cast<void*>(&event.native_event));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
absl::Status Controller::OnLoad() {
|
||||
if (editor_manager_.quit() || !window_.active_) {
|
||||
if (!window_backend_) {
|
||||
return absl::InternalError("Window backend not initialized");
|
||||
}
|
||||
|
||||
if (editor_manager_.quit() || !window_backend_->IsActive()) {
|
||||
active_ = false;
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE != 1
|
||||
ImGui_ImplSDLRenderer2_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
// Start new ImGui frame via backend (handles SDL2/SDL3 automatically)
|
||||
window_backend_->NewImGuiFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->WorkPos);
|
||||
ImGui::SetNextWindowSize(viewport->WorkSize);
|
||||
|
||||
// Calculate layout offsets for sidebars and status bar
|
||||
const float left_offset = editor_manager_.GetLeftLayoutOffset();
|
||||
const float right_offset = editor_manager_.GetRightLayoutOffset();
|
||||
const float bottom_offset = editor_manager_.GetBottomLayoutOffset();
|
||||
|
||||
// Adjust dockspace position and size for sidebars and status bar
|
||||
ImVec2 dockspace_pos = viewport->WorkPos;
|
||||
ImVec2 dockspace_size = viewport->WorkSize;
|
||||
|
||||
dockspace_pos.x += left_offset;
|
||||
dockspace_size.x -= (left_offset + right_offset);
|
||||
dockspace_size.y -= bottom_offset; // Reserve space for status bar at bottom
|
||||
|
||||
ImGui::SetNextWindowPos(dockspace_pos);
|
||||
ImGui::SetNextWindowSize(dockspace_size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGuiWindowFlags window_flags =
|
||||
ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
// Check if menu bar should be visible (WASM can hide it for clean UI)
|
||||
bool show_menu_bar = true;
|
||||
if (editor_manager_.ui_coordinator()) {
|
||||
show_menu_bar = editor_manager_.ui_coordinator()->IsMenuBarVisible();
|
||||
}
|
||||
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking;
|
||||
if (show_menu_bar) {
|
||||
window_flags |= ImGuiWindowFlags_MenuBar;
|
||||
}
|
||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
window_flags |=
|
||||
@@ -83,15 +146,22 @@ absl::Status Controller::OnLoad() {
|
||||
ImGui::Begin("DockSpaceWindow", nullptr, window_flags);
|
||||
ImGui::PopStyleVar(3);
|
||||
|
||||
// Create DockSpace first
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
// Create DockSpace with adjusted size
|
||||
ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
|
||||
gui::DockSpaceRenderer::BeginEnhancedDockSpace(
|
||||
dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
|
||||
editor_manager_.DrawMenuBar(); // Draw the fixed menu bar at the top
|
||||
if (show_menu_bar) {
|
||||
editor_manager_.DrawMenuBar(); // Draw the fixed menu bar at the top
|
||||
}
|
||||
|
||||
gui::DockSpaceRenderer::EndEnhancedDockSpace();
|
||||
ImGui::End();
|
||||
|
||||
// Draw menu bar restore button when menu is hidden (WASM)
|
||||
if (!show_menu_bar && editor_manager_.ui_coordinator()) {
|
||||
editor_manager_.ui_coordinator()->DrawMenuBarRestoreButton();
|
||||
}
|
||||
#endif
|
||||
gui::WidgetIdRegistry::Instance().BeginFrame();
|
||||
absl::Status update_status = editor_manager_.Update();
|
||||
@@ -101,17 +171,22 @@ absl::Status Controller::OnLoad() {
|
||||
}
|
||||
|
||||
void Controller::DoRender() const {
|
||||
// Process all pending texture commands (batched to max 8 per frame).
|
||||
if (!window_backend_ || !renderer_) return;
|
||||
|
||||
// Process pending texture commands (max 8 per frame for consistent performance)
|
||||
gfx::Arena::Get().ProcessTextureQueue(renderer_.get());
|
||||
|
||||
ImGui::Render();
|
||||
renderer_->Clear();
|
||||
ImGui_ImplSDLRenderer2_RenderDrawData(
|
||||
ImGui::GetDrawData(),
|
||||
static_cast<SDL_Renderer*>(renderer_->GetBackendRenderer()));
|
||||
|
||||
// Render ImGui draw data and handle viewports via backend
|
||||
window_backend_->RenderImGui(renderer_.get());
|
||||
|
||||
renderer_->Present();
|
||||
|
||||
// Use TimingManager for accurate frame timing in sync with SDL
|
||||
// Process any pending screenshot requests on the main thread after present
|
||||
ProcessScreenshotRequests();
|
||||
|
||||
// Get delta time AFTER render for accurate measurement
|
||||
float delta_time = TimingManager::Get().Update();
|
||||
|
||||
// Gentle frame rate cap to prevent excessive CPU usage
|
||||
@@ -122,8 +197,42 @@ void Controller::DoRender() const {
|
||||
}
|
||||
|
||||
void Controller::OnExit() {
|
||||
renderer_->Shutdown();
|
||||
PRINT_IF_ERROR(ShutdownWindow(window_));
|
||||
if (renderer_) {
|
||||
renderer_->Shutdown();
|
||||
}
|
||||
if (window_backend_) {
|
||||
window_backend_->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
absl::Status Controller::LoadRomForTesting(const std::string& rom_path) {
|
||||
// Use EditorManager's OpenRomOrProject which handles the full initialization:
|
||||
// 1. Load ROM file into session
|
||||
// 2. ConfigureEditorDependencies()
|
||||
// 3. LoadAssets() - initializes all editors and loads graphics
|
||||
// 4. Updates UI state (hides welcome screen, etc.)
|
||||
return editor_manager_.OpenRomOrProject(rom_path);
|
||||
}
|
||||
|
||||
void Controller::RequestScreenshot(const ScreenshotRequest& request) {
|
||||
std::lock_guard<std::mutex> lock(screenshot_mutex_);
|
||||
screenshot_requests_.push(request);
|
||||
}
|
||||
|
||||
void Controller::ProcessScreenshotRequests() const {
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
std::lock_guard<std::mutex> lock(screenshot_mutex_);
|
||||
while (!screenshot_requests_.empty()) {
|
||||
auto request = screenshot_requests_.front();
|
||||
screenshot_requests_.pop();
|
||||
|
||||
// Perform capture on main thread
|
||||
auto result = test::CaptureHarnessScreenshot(request.preferred_path);
|
||||
if (request.callback) {
|
||||
request.callback(result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
Reference in New Issue
Block a user