From 5421f7945d9d6486eb72b5a43fe451b2182ed2b5 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 4 Jan 2026 13:38:11 +0000 Subject: [PATCH] feat: Add application, lifecycle, and render controllers for service orchestration --- CMakeLists.txt | 3 + src/controllers/application_controller.cpp | 66 ++++++++++++++++++++++ src/controllers/application_controller.hpp | 37 ++++++++++++ src/controllers/lifecycle_controller.cpp | 35 ++++++++++++ src/controllers/lifecycle_controller.hpp | 35 ++++++++++++ src/controllers/render_controller.cpp | 65 +++++++++++++++++++++ src/controllers/render_controller.hpp | 33 +++++++++++ 7 files changed, 274 insertions(+) create mode 100644 src/controllers/application_controller.cpp create mode 100644 src/controllers/application_controller.hpp create mode 100644 src/controllers/lifecycle_controller.cpp create mode 100644 src/controllers/lifecycle_controller.hpp create mode 100644 src/controllers/render_controller.cpp create mode 100644 src/controllers/render_controller.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fd0aef7..e9a7624 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,9 @@ if(BUILD_SDL3_APP) src/services/impl/vulkan_gui_service.cpp src/services/impl/bullet_physics_service.cpp src/services/impl/lua_script_service.cpp + src/controllers/application_controller.cpp + src/controllers/render_controller.cpp + src/controllers/lifecycle_controller.cpp src/app/sdl3_app_core.cpp src/app/audio_player.cpp src/app/sdl3_app_device.cpp diff --git a/src/controllers/application_controller.cpp b/src/controllers/application_controller.cpp new file mode 100644 index 0000000..c81e5d3 --- /dev/null +++ b/src/controllers/application_controller.cpp @@ -0,0 +1,66 @@ +#include "application_controller.hpp" +#include "../logging/logger.hpp" +#include "../services/interfaces/i_window_service.hpp" +#include "../services/interfaces/i_input_service.hpp" +#include "../events/event_bus.hpp" +#include "../events/event_types.hpp" + +namespace sdl3cpp::controllers { + +ApplicationController::ApplicationController(di::ServiceRegistry& registry) + : registry_(registry), running_(false) { + logging::TraceGuard trace; +} + +ApplicationController::~ApplicationController() { + logging::TraceGuard trace; +} + +void ApplicationController::Run() { + logging::TraceGuard trace; + logging::Logger::GetInstance().Info("Application starting main loop"); + + running_ = true; + auto lastTime = std::chrono::high_resolution_clock::now(); + + while (running_) { + auto currentTime = std::chrono::high_resolution_clock::now(); + float deltaTime = std::chrono::duration(currentTime - lastTime).count(); + lastTime = currentTime; + + HandleEvents(); + ProcessFrame(deltaTime); + } + + logging::Logger::GetInstance().Info("Application exiting main loop"); +} + +void ApplicationController::HandleEvents() { + // Window service polls SDL events and publishes to event bus + auto windowService = registry_.GetService(); + if (windowService) { + windowService->PollEvents(); + } + + // Check for quit events + auto eventBus = registry_.GetService(); + if (eventBus) { + // Process queued events + eventBus->ProcessQueue(); + } + + // Check if window should close + if (windowService && windowService->ShouldClose()) { + running_ = false; + } +} + +void ApplicationController::ProcessFrame(float deltaTime) { + logging::TraceGuard trace; + + // Render controller will handle rendering pipeline + // Physics, scripts, audio updates happen here + // This is a placeholder - full implementation in RenderController +} + +} // namespace sdl3cpp::controllers diff --git a/src/controllers/application_controller.hpp b/src/controllers/application_controller.hpp new file mode 100644 index 0000000..316ed44 --- /dev/null +++ b/src/controllers/application_controller.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "../di/service_registry.hpp" +#include + +namespace sdl3cpp::controllers { + +/** + * @brief Main application controller. + * + * Orchestrates the main game loop and coordinates all subsystems. + * Replaces Sdl3App::MainLoop() with clean service-based architecture. + */ +class ApplicationController { +public: + explicit ApplicationController(di::ServiceRegistry& registry); + ~ApplicationController(); + + ApplicationController(const ApplicationController&) = delete; + ApplicationController& operator=(const ApplicationController&) = delete; + + /** + * @brief Run the main application loop. + * + * Processes events, updates game state, and renders frames until quit. + */ + void Run(); + +private: + void ProcessFrame(float deltaTime); + void HandleEvents(); + + di::ServiceRegistry& registry_; + bool running_ = false; +}; + +} // namespace sdl3cpp::controllers diff --git a/src/controllers/lifecycle_controller.cpp b/src/controllers/lifecycle_controller.cpp new file mode 100644 index 0000000..e39cc16 --- /dev/null +++ b/src/controllers/lifecycle_controller.cpp @@ -0,0 +1,35 @@ +#include "lifecycle_controller.hpp" +#include "../logging/logger.hpp" + +namespace sdl3cpp::controllers { + +LifecycleController::LifecycleController(di::ServiceRegistry& registry) + : registry_(registry) { + logging::TraceGuard trace; +} + +LifecycleController::~LifecycleController() { + logging::TraceGuard trace; +} + +void LifecycleController::InitializeAll() { + logging::TraceGuard trace; + logging::Logger::GetInstance().Info("Initializing all services"); + + // ServiceRegistry handles initialization order based on dependencies + registry_.InitializeAll(); + + logging::Logger::GetInstance().Info("All services initialized"); +} + +void LifecycleController::ShutdownAll() noexcept { + logging::TraceGuard trace; + logging::Logger::GetInstance().Info("Shutting down all services"); + + // ServiceRegistry handles shutdown in reverse dependency order + registry_.ShutdownAll(); + + logging::Logger::GetInstance().Info("All services shutdown"); +} + +} // namespace sdl3cpp::controllers diff --git a/src/controllers/lifecycle_controller.hpp b/src/controllers/lifecycle_controller.hpp new file mode 100644 index 0000000..7fee97a --- /dev/null +++ b/src/controllers/lifecycle_controller.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "../di/service_registry.hpp" + +namespace sdl3cpp::controllers { + +/** + * @brief Lifecycle controller. + * + * Manages initialization and shutdown sequencing of all services. + * Ensures proper dependency order and resource cleanup. + */ +class LifecycleController { +public: + explicit LifecycleController(di::ServiceRegistry& registry); + ~LifecycleController(); + + LifecycleController(const LifecycleController&) = delete; + LifecycleController& operator=(const LifecycleController&) = delete; + + /** + * @brief Initialize all services in correct order. + */ + void InitializeAll(); + + /** + * @brief Shutdown all services in reverse order. + */ + void ShutdownAll() noexcept; + +private: + di::ServiceRegistry& registry_; +}; + +} // namespace sdl3cpp::controllers diff --git a/src/controllers/render_controller.cpp b/src/controllers/render_controller.cpp new file mode 100644 index 0000000..563ddb9 --- /dev/null +++ b/src/controllers/render_controller.cpp @@ -0,0 +1,65 @@ +#include "render_controller.hpp" +#include "../logging/logger.hpp" +#include "../services/interfaces/i_graphics_service.hpp" +#include "../services/interfaces/i_script_service.hpp" +#include "../services/interfaces/i_gui_service.hpp" + +namespace sdl3cpp::controllers { + +RenderController::RenderController(di::ServiceRegistry& registry) + : registry_(registry) { + logging::TraceGuard trace; +} + +RenderController::~RenderController() { + logging::TraceGuard trace; +} + +void RenderController::RenderFrame(float time) { + logging::TraceGuard trace; + + // Get required services + auto graphicsService = registry_.GetService(); + auto scriptService = registry_.GetService(); + auto guiService = registry_.GetService(); + + if (!graphicsService) { + logging::Logger::GetInstance().Error("Graphics service not available"); + return; + } + + // Begin frame + graphicsService->BeginFrame(); + + // Load scene objects from script + if (scriptService) { + auto sceneObjects = scriptService->LoadSceneObjects(); + + // Compute model matrices and build render commands + std::vector renderCommands; + for (const auto& obj : sceneObjects) { + auto modelMatrix = scriptService->ComputeModelMatrix(obj.computeModelMatrixRef, time); + // Build render command from scene object + // This would create RenderCommand with vertices, indices, modelMatrix, shaderKey + } + + // Get view-projection matrix + float aspect = 1920.0f / 1080.0f; // TODO: Get from window service + auto viewProj = scriptService->GetViewProjectionMatrix(aspect); + + // Render scene + // graphicsService->RenderScene(renderCommands, viewProj); + } + + // Render GUI overlay + if (guiService && scriptService && scriptService->HasGuiCommands()) { + auto guiCommands = scriptService->LoadGuiCommands(); + // guiService->PrepareFrame(guiCommands, width, height); + // guiService->RenderToSwapchain(commandBuffer, swapchainImage); + } + + // End frame and present + graphicsService->EndFrame(); +} + +} // namespace sdl3cpp::controllers diff --git a/src/controllers/render_controller.hpp b/src/controllers/render_controller.hpp new file mode 100644 index 0000000..34efeab --- /dev/null +++ b/src/controllers/render_controller.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "../di/service_registry.hpp" +#include + +namespace sdl3cpp::controllers { + +/** + * @brief Render controller. + * + * Coordinates the rendering pipeline across graphics, scene, GUI, and script services. + * Extracted from Sdl3App rendering logic. + */ +class RenderController { +public: + explicit RenderController(di::ServiceRegistry& registry); + ~RenderController(); + + RenderController(const RenderController&) = delete; + RenderController& operator=(const RenderController&) = delete; + + /** + * @brief Render a single frame. + * + * @param time Current time in seconds for animations + */ + void RenderFrame(float time); + +private: + di::ServiceRegistry& registry_; +}; + +} // namespace sdl3cpp::controllers