#include "service_based_app.hpp" #include "events/event_bus.hpp" #include "events/i_event_bus.hpp" #include "services/interfaces/i_window_service.hpp" #include "services/interfaces/i_graphics_service.hpp" #include "services/impl/json_config_service.hpp" #include "services/impl/platform_service.hpp" #include "services/impl/sdl_window_service.hpp" #include "services/impl/sdl_input_service.hpp" #include "services/impl/vulkan_device_service.hpp" #include "services/impl/swapchain_service.hpp" #include "services/impl/pipeline_service.hpp" #include "services/impl/buffer_service.hpp" #include "services/impl/render_command_service.hpp" #include "services/impl/graphics_service.hpp" #include "services/impl/script_engine_service.hpp" #include "services/impl/scene_script_service.hpp" #include "services/impl/shader_script_service.hpp" #include "services/impl/gui_script_service.hpp" #include "services/impl/audio_command_service.hpp" #include "services/impl/physics_bridge_service.hpp" #include "services/impl/mesh_service.hpp" #include "services/impl/scene_service.hpp" #include "services/impl/sdl_audio_service.hpp" #include "services/impl/vulkan_gui_service.hpp" #include "services/impl/bullet_physics_service.hpp" #include "services/impl/crash_recovery_service.hpp" #include "services/impl/logger_service.hpp" #include "services/interfaces/i_platform_service.hpp" #include #include namespace sdl3cpp::app { ServiceBasedApp::ServiceBasedApp(const std::filesystem::path& scriptPath) : scriptPath_(scriptPath) { // Register logger service first registry_.RegisterService(); logger_ = registry_.GetService(); logger_->Trace("ServiceBasedApp", "ServiceBasedApp", "scriptPath=" + scriptPath_.string(), "constructor starting"); try { logger_->Info("ServiceBasedApp::ServiceBasedApp: Setting up SDL"); SetupSDL(); logger_->Info("ServiceBasedApp::ServiceBasedApp: Registering services"); RegisterServices(); // Get and initialize crash recovery service crashRecoveryService_ = registry_.GetService(); if (crashRecoveryService_) { crashRecoveryService_->Initialize(); } logger_->Info("ServiceBasedApp::ServiceBasedApp: Creating controllers"); lifecycleController_ = std::make_unique(registry_); applicationController_ = std::make_unique(registry_); logger_->Info("ServiceBasedApp::ServiceBasedApp: constructor completed"); } catch (const std::exception& e) { if (logger_) { logger_->Error("ServiceBasedApp::ServiceBasedApp: Failed to initialize ServiceBasedApp: " + std::string(e.what())); } else { // Fallback to console if logger not available std::cerr << "ServiceBasedApp::ServiceBasedApp: Failed to initialize ServiceBasedApp: " << e.what() << std::endl; } throw; } } ServiceBasedApp::~ServiceBasedApp() { logger_->Trace("ServiceBasedApp", "~ServiceBasedApp", "", "Entering"); // Shutdown crash recovery service if (crashRecoveryService_) { crashRecoveryService_->Shutdown(); } applicationController_.reset(); lifecycleController_.reset(); logger_->Trace("ServiceBasedApp", "~ServiceBasedApp", "", "Exiting"); } void ServiceBasedApp::Run() { logger_->Trace("ServiceBasedApp", "Run", "", "Entering"); try { // Initialize all services lifecycleController_->InitializeAll(); // Create the window auto windowService = registry_.GetService(); if (windowService) { services::WindowConfig config; config.width = 1024; config.height = 768; config.title = "SDL3 + Vulkan Application"; config.resizable = true; windowService->CreateWindow(config); } // Initialize graphics after window is created auto graphicsService = registry_.GetService(); if (graphicsService && windowService) { services::GraphicsConfig graphicsConfig; graphicsConfig.deviceExtensions = {"VK_KHR_swapchain"}; graphicsConfig.enableValidationLayers = false; graphicsService->InitializeDevice(windowService->GetNativeHandle(), graphicsConfig); graphicsService->InitializeSwapchain(); } // Run the main application loop with crash recovery if (crashRecoveryService_) { bool success = crashRecoveryService_->ExecuteWithTimeout( [this]() { applicationController_->Run(); }, 30000, // 30 second timeout for the main loop "Main Application Loop" ); if (!success) { logger_->Warn("ServiceBasedApp::Run: Main loop timed out, attempting recovery"); if (crashRecoveryService_->AttemptRecovery()) { logger_->Info("ServiceBasedApp::Run: Recovery successful, restarting main loop"); applicationController_->Run(); // Try again } } } else { // Fallback if no crash recovery service applicationController_->Run(); } // Shutdown all services lifecycleController_->ShutdownAll(); logger_->Trace("ServiceBasedApp", "Run", "", "Exiting"); } catch (const std::exception& e) { logger_->Error("ServiceBasedApp::Run: Application error: " + std::string(e.what())); // Attempt recovery on exception if (crashRecoveryService_ && crashRecoveryService_->AttemptRecovery()) { logger_->Info("ServiceBasedApp::Run: Recovered from exception"); } else { throw; } } } void ServiceBasedApp::ConfigureLogging(services::LogLevel level, bool enableConsole, const std::string& outputFile) { if (logger_) { logger_->SetLevel(level); logger_->EnableConsoleOutput(enableConsole); if (!outputFile.empty()) { logger_->SetOutputFile(outputFile); } } } void ServiceBasedApp::SetupSDL() { logger_->Trace("ServiceBasedApp", "SetupSDL", "", "Entering"); // SDL initialization is handled by the window service // Don't initialize SDL here to avoid double initialization logger_->Trace("ServiceBasedApp", "SetupSDL", "", "Exiting"); } void ServiceBasedApp::RegisterServices() { logger_->Trace("ServiceBasedApp", "RegisterServices", "", "Entering"); // Logger service already registered in constructor // Crash recovery service (needed early for crash detection) registry_.RegisterService( registry_.GetService()); // Platform service (needed for SDL error enrichment) registry_.RegisterService( registry_.GetService()); // Event bus (needed by window service) registry_.RegisterService(); // Configuration service services::impl::RuntimeConfig runtimeConfig; runtimeConfig.scriptPath = scriptPath_; registry_.RegisterService( registry_.GetService(), runtimeConfig); // Window service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Input service registry_.RegisterService( registry_.GetService(), registry_.GetService()); // Audio service (needed before script bindings execute) registry_.RegisterService( registry_.GetService()); // Script bridge services registry_.RegisterService( registry_.GetService()); registry_.RegisterService( registry_.GetService()); registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Script engine service (shared Lua runtime) registry_.RegisterService( scriptPath_, registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), runtimeConfig.luaDebug); // Script-facing services registry_.RegisterService( registry_.GetService()); registry_.RegisterService( registry_.GetService()); registry_.RegisterService( registry_.GetService()); // Connect input service to GUI script service for GUI input processing auto inputService = registry_.GetService(); auto guiScriptService = registry_.GetService(); if (inputService && guiScriptService) { inputService->SetGuiScriptService(guiScriptService.get()); } // Vulkan device service registry_.RegisterService( registry_.GetService()); // Swapchain service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Pipeline service registry_.RegisterService( registry_.GetService(), registry_.GetService()); // Buffer service registry_.RegisterService( registry_.GetService(), registry_.GetService()); // Render command service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Graphics service (facade) registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService()); // Scene service registry_.RegisterService( registry_.GetService(), registry_.GetService()); // GUI service registry_.RegisterService( registry_.GetService(), registry_.GetService()); // Physics service registry_.RegisterService( registry_.GetService()); logger_->Trace("ServiceBasedApp", "RegisterServices", "", "Exiting"); } } // namespace sdl3cpp::app