#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/interfaces/i_application_loop_service.hpp" #include "services/interfaces/i_lifecycle_service.hpp" #include "services/impl/json_config_service.hpp" #include "services/impl/lifecycle_service.hpp" #include "services/impl/application_loop_service.hpp" #include "services/impl/render_coordinator_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/vulkan_graphics_backend.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/render_graph_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/gui_renderer_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 #include namespace sdl3cpp::app { ServiceBasedApp::ServiceBasedApp(services::RuntimeConfig runtimeConfig, services::LogLevel logLevel) : runtimeConfig_(std::move(runtimeConfig)) { // Register logger service first registry_.RegisterService(); logger_ = registry_.GetService(); if (logger_) { logger_->SetLevel(logLevel); } logger_->Trace("ServiceBasedApp", "ServiceBasedApp", "scriptPath=" + runtimeConfig_.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: Resolving lifecycle services"); lifecycleService_ = registry_.GetService(); applicationLoopService_ = registry_.GetService(); renderCoordinatorService_ = registry_.GetService(); 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(); } renderCoordinatorService_.reset(); applicationLoopService_.reset(); lifecycleService_.reset(); logger_->Trace("ServiceBasedApp", "~ServiceBasedApp", "", "Exiting"); } void ServiceBasedApp::Run() { logger_->Trace("ServiceBasedApp", "Run", "", "Entering"); try { // Initialize all services lifecycleService_->InitializeAll(); // Create the window auto windowService = registry_.GetService(); auto configService = registry_.GetService(); if (windowService) { services::WindowConfig config; if (configService) { config.width = configService->GetWindowWidth(); config.height = configService->GetWindowHeight(); config.title = configService->GetWindowTitle(); config.mouseGrab = configService->GetMouseGrabConfig(); } else { config.width = runtimeConfig_.width; config.height = runtimeConfig_.height; config.title = runtimeConfig_.windowTitle; config.mouseGrab = runtimeConfig_.mouseGrab; } config.resizable = true; windowService->CreateWindow(config); } // Initialize graphics after window is created auto graphicsService = registry_.GetService(); if (graphicsService && windowService) { services::GraphicsConfig graphicsConfig; if (configService) { graphicsConfig.deviceExtensions = configService->GetDeviceExtensions(); } else { graphicsConfig.deviceExtensions = {"VK_KHR_swapchain"}; } graphicsConfig.enableValidationLayers = false; graphicsService->InitializeDevice(windowService->GetNativeHandle(), graphicsConfig); graphicsService->InitializeSwapchain(); } // Initialize GUI service after graphics auto guiService = registry_.GetService(); auto vulkanDeviceService = registry_.GetService(); auto swapchainService = registry_.GetService(); if (guiService && vulkanDeviceService && swapchainService) { guiService->Initialize(vulkanDeviceService->GetDevice(), vulkanDeviceService->GetPhysicalDevice(), swapchainService->GetSwapchainImageFormat(), swapchainService->GetRenderPass(), runtimeConfig_.scriptPath.parent_path()); } // Run the main application loop with crash recovery if (crashRecoveryService_) { bool success = crashRecoveryService_->ExecuteWithTimeout( [this]() { applicationLoopService_->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"); applicationLoopService_->Run(); // Try again } } } else { // Fallback if no crash recovery service applicationLoopService_->Run(); } // Shutdown all services lifecycleService_->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()); // Lifecycle service registry_.RegisterService( registry_, registry_.GetService()); // Platform service (needed for SDL error enrichment) registry_.RegisterService( registry_.GetService()); // Event bus (needed by window service) registry_.RegisterService(); // Configuration service registry_.RegisterService( registry_.GetService(), runtimeConfig_); // Window service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Input service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Audio service (needed before script bindings execute) registry_.RegisterService( registry_.GetService()); // Script bridge services registry_.RegisterService( registry_.GetService(), registry_.GetService()); registry_.RegisterService( registry_.GetService()); registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); // Script engine service (shared Lua runtime) registry_.RegisterService( runtimeConfig_.scriptPath, registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), runtimeConfig_.luaDebug); // Script-facing services registry_.RegisterService( registry_.GetService(), registry_.GetService()); registry_.RegisterService( registry_.GetService(), registry_.GetService()); registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService()); logger_->Trace("ServiceBasedApp", "RegisterServices", "Registered render graph script service"); registry_.RegisterService( registry_.GetService(), 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()); // GUI renderer service (needed by render command service and GUI service) registry_.RegisterService( registry_.GetService(), registry_.GetService()); logger_->Trace("ServiceBasedApp", "RegisterServices", "Registered GUI renderer service before render command service"); // Render command service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), std::static_pointer_cast(registry_.GetService()), registry_.GetService()); // Graphics service (facade) registry_.RegisterService( registry_.GetService(), std::make_shared( 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()); // Render coordinator service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService()); // Application loop service registry_.RegisterService( registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService(), registry_.GetService()); logger_->Trace("ServiceBasedApp", "RegisterServices", "", "Exiting"); } } // namespace sdl3cpp::app