#pragma once #include #include #include #include #include #include // --- Clase PauseManager: maneja el sistema de pausa del juego --- class PauseManager { public: // --- Enums --- enum class Source : uint8_t { // Fuentes de pausa NONE = 0, PLAYER = 1 << 0, // 0001 SERVICE_MENU = 1 << 1, // 0010 FOCUS_LOST = 1 << 2 // 0100 }; // --- Operadores friend --- friend auto operator|(Source a, Source b) -> Source { return static_cast(static_cast(a) | static_cast(b)); // NOLINT(readability-redundant-casting) } friend auto operator&(Source a, Source b) -> Source { return static_cast(static_cast(a) & static_cast(b)); // NOLINT(readability-redundant-casting) } friend auto operator~(Source a) -> uint8_t { return ~static_cast(a); } friend auto operator&=(Source& a, uint8_t b) -> Source& { a = static_cast(static_cast(a) & b); return a; } friend auto operator|=(Source& a, Source b) -> Source& { return a = a | b; } friend auto operator&=(Source& a, Source b) -> Source& { return a = a & b; } // --- Constructor y destructor --- explicit PauseManager(std::function callback = nullptr) // Constructor con callback opcional : on_pause_changed_callback_(std::move(callback)) {} // --- Métodos principales --- void setFlag(Source source, bool enable) { // Establece/quita una fuente de pausa específica const bool WAS_PAUSED = isPaused(); if (enable) { flags_ |= source; } else { flags_ &= ~source; // Ahora funciona: Source &= uint8_t } // cppcheck-suppress knownConditionTrueFalse // false-positive: flags_ ha estat modificat entre les dues crides a isPaused() if (WAS_PAUSED != isPaused()) { notifyPauseChanged(); } } // --- Métodos específicos para cada fuente --- void setPlayerPause(bool enable) { setFlag(Source::PLAYER, enable); } void setServiceMenuPause(bool enable) { setFlag(Source::SERVICE_MENU, enable); } void setFocusLossPause(bool enable) { setFlag(Source::FOCUS_LOST, enable); } void togglePlayerPause() { setPlayerPause(!isPlayerPaused()); } // Toggle para el jugador (más común) // --- Getters --- [[nodiscard]] auto isPaused() const -> bool { return flags_ != Source::NONE; } [[nodiscard]] auto isPlayerPaused() const -> bool { return hasFlag(Source::PLAYER); } [[nodiscard]] auto isServiceMenuPaused() const -> bool { return hasFlag(Source::SERVICE_MENU); } [[nodiscard]] auto isFocusLossPaused() const -> bool { return hasFlag(Source::FOCUS_LOST); } [[nodiscard]] auto getFlags() const -> Source { return flags_; } // Obtiene las banderas actuales // --- Métodos de utilidad --- void clearAll() { // Limpia todas las pausas (útil para reset) if (isPaused()) { flags_ = Source::NONE; notifyPauseChanged(); } } [[nodiscard]] auto getStatusString() const -> std::string { // Método para debug if (flags_ == Source::NONE) { return "Active"; } std::vector parts; if (hasFlag(Source::PLAYER)) { parts.emplace_back("Player"); } if (hasFlag(Source::SERVICE_MENU)) { parts.emplace_back("ServiceMenu"); } if (hasFlag(Source::FOCUS_LOST)) { parts.emplace_back("FocusLoss"); } std::string result = "Paused by: "; for (size_t i = 0; i < parts.size(); ++i) { if (i > 0) { result += ", "; } result += parts[i]; } return result; } void setCallback(std::function callback) { // Permite cambiar el callback en runtime on_pause_changed_callback_ = std::move(callback); } private: // --- Variables --- Source flags_ = Source::NONE; std::function on_pause_changed_callback_; // --- Métodos internos --- [[nodiscard]] auto hasFlag(Source flag) const -> bool { return (flags_ & flag) != Source::NONE; } void notifyPauseChanged() { if (on_pause_changed_callback_) { on_pause_changed_callback_(isPaused()); } } };