#include "window_manager.h" #include // for SDL_Init #include // for SDL_GetError #include // for SDL_CreateWindow, SDL_GetDisplayBounds #include // for cout // Incluir backends específicos // TODO: Reactivar cuando se implemente compilación Objective-C++ // #ifdef __APPLE__ // #include "backends/metal_renderer.h" // #endif #if defined(_WIN32) || defined(__linux__) #include "backends/vulkan_renderer.h" #endif // Fallback SDL siempre disponible #include "backends/sdl_renderer.h" namespace vibe4 { WindowManager::WindowManager() = default; WindowManager::~WindowManager() { shutdown(); } bool WindowManager::initialize(const char* title, int width, int height, int zoom) { logical_width_ = width; logical_height_ = height; current_zoom_ = zoom; // Inicializar SDL if (!SDL_Init(SDL_INIT_VIDEO)) { std::cout << "¡SDL no se pudo inicializar! Error: " << SDL_GetError() << std::endl; return false; } // Crear ventana SDL if (!createSDLWindow(title, width * zoom, height * zoom)) { return false; } // Detectar y crear el mejor backend disponible BackendType backend_type = detectBestBackend(); renderer_ = createRenderer(backend_type); if (!renderer_) { std::cout << "¡No se pudo crear ningún backend de renderizado!" << std::endl; return false; } // Inicializar el renderer if (!renderer_->initialize(window_, width, height)) { std::cout << "¡No se pudo inicializar el backend " << renderer_->getBackendName() << "!" << std::endl; return false; } std::cout << "Backend de renderizado inicializado: " << renderer_->getBackendName() << std::endl; return true; } void WindowManager::shutdown() { if (renderer_) { renderer_->shutdown(); renderer_.reset(); } if (window_) { SDL_DestroyWindow(window_); window_ = nullptr; } SDL_Quit(); } bool WindowManager::createSDLWindow(const char* title, int width, int height) { Uint32 window_flags = SDL_WINDOW_OPENGL; // Empezamos con OpenGL como base // Agregar flags específicos dependiendo del backend que vayamos a usar BackendType backend_type = detectBestBackend(); switch (backend_type) { case BackendType::METAL: window_flags = SDL_WINDOW_METAL; break; case BackendType::VULKAN: window_flags = SDL_WINDOW_VULKAN; break; case BackendType::SDL: default: window_flags = SDL_WINDOW_OPENGL; break; } window_ = SDL_CreateWindow(title, width, height, window_flags); if (!window_) { std::cout << "¡No se pudo crear la ventana! Error: " << SDL_GetError() << std::endl; return false; } return true; } BackendType WindowManager::detectBestBackend() const { // TODO: Reactivar Metal cuando se implemente compilación Objective-C++ #ifdef __APPLE__ return BackendType::SDL; // Temporalmente usar SDL en macOS #elif defined(_WIN32) || defined(__linux__) return BackendType::VULKAN; // Windows/Linux usan Vulkan #else return BackendType::SDL; // Fallback para otras plataformas #endif } std::unique_ptr WindowManager::createRenderer(BackendType type) { switch (type) { // TODO: Reactivar cuando se implemente compilación Objective-C++ // #ifdef __APPLE__ // case BackendType::METAL: // return std::make_unique(); // #endif #if defined(_WIN32) || defined(__linux__) case BackendType::VULKAN: return std::make_unique(); #endif case BackendType::SDL: default: return std::make_unique(); } } void WindowManager::setTitle(const char* title) { if (window_) { SDL_SetWindowTitle(window_, title); } } bool WindowManager::setFullscreen(bool enable) { if (!window_) return false; bool result = SDL_SetWindowFullscreen(window_, enable); if (result) { fullscreen_enabled_ = enable; if (enable) { real_fullscreen_enabled_ = false; // Solo uno puede estar activo } } return result; } bool WindowManager::setRealFullscreen(bool enable) { if (!window_) return false; bool result = SDL_SetWindowFullscreen(window_, enable); if (result) { real_fullscreen_enabled_ = enable; if (enable) { fullscreen_enabled_ = false; // Solo uno puede estar activo } } return result; } void WindowManager::setZoom(int zoom) { if (zoom < MIN_ZOOM || zoom > MAX_ZOOM) return; current_zoom_ = zoom; updateWindowSize(); } void WindowManager::updateWindowSize() { if (!window_ || fullscreen_enabled_ || real_fullscreen_enabled_) return; int new_width = logical_width_ * current_zoom_; int new_height = logical_height_ * current_zoom_; SDL_SetWindowSize(window_, new_width, new_height); if (renderer_) { renderer_->resize(logical_width_, logical_height_); } } int WindowManager::calculateMaxZoom() const { SDL_Rect display_bounds; if (!SDL_GetDisplayBounds(SDL_GetDisplayForWindow(window_), &display_bounds)) { return MIN_ZOOM; } int max_width = display_bounds.w - DESKTOP_MARGIN * 2; int max_height = display_bounds.h - DESKTOP_MARGIN * 2 - DECORATION_HEIGHT; int max_zoom_x = max_width / logical_width_; int max_zoom_y = max_height / logical_height_; int calculated_max = std::min(max_zoom_x, max_zoom_y); return std::min(calculated_max, MAX_ZOOM); } void WindowManager::zoomIn() { int max_zoom = calculateMaxZoom(); if (current_zoom_ < max_zoom) { setZoom(current_zoom_ + 1); } } void WindowManager::zoomOut() { if (current_zoom_ > MIN_ZOOM) { setZoom(current_zoom_ - 1); } } void WindowManager::getSize(int& width, int& height) const { if (window_) { SDL_GetWindowSize(window_, &width, &height); } else { width = height = 0; } } void WindowManager::getLogicalSize(int& width, int& height) const { width = logical_width_; height = logical_height_; } BackendType WindowManager::getBackendType() const { return renderer_ ? renderer_->getBackendType() : BackendType::SDL; } const char* WindowManager::getBackendName() const { return renderer_ ? renderer_->getBackendName() : "None"; } } // namespace vibe4