// SPDX-License-Identifier: MIT // // ES-DE Frontend // ViewController.h // // Handles overall system navigation including animations and transitions. // Creates the gamelist views and handles refresh and reloads of these when needed // (for example when metadata has been changed or when a list sorting has taken place). // Initiates the launching of games, calling FileData to do the actual launch. // Displays a dialog when there are no games found on startup. // #ifndef ES_APP_VIEWS_VIEW_CONTROLLER_H #define ES_APP_VIEWS_VIEW_CONTROLLER_H #include "FileData.h" #include "GuiComponent.h" #include "guis/GuiMsgBox.h" #include "renderers/Renderer.h" #include "utils/StringUtil.h" #include class GamelistView; class SystemData; class SystemView; // Handles transitions between views, e.g. from system to system and from gamelist to gamelist. // Also sets up the initial gamelists and refreshes and reloads them as required. class ViewController : public GuiComponent { public: static ViewController* getInstance(); // These functions are called from main(). void setMenuColors(); void legacyAppDataDialog(); void migratedAppDataFilesDialog(); void unsafeUpgradeDialog(); void invalidSystemsFileDialog(); void noGamesDialog(); void invalidAlternativeEmulatorDialog(); void updateAvailableDialog(); // Try to completely populate the GamelistView map. // Caches things so there's no pauses during transitions. void preload(); // If a basic view detected a metadata change, it can request to recreate // the current gamelist view (as it may change to be detailed). void reloadGamelistView(GamelistView* gamelist, bool reloadTheme = false); void reloadGamelistView(SystemData* system, bool reloadTheme = false) { reloadGamelistView(getGamelistView(system).get(), reloadTheme); } // Reload everything with a theme, used when the "Theme" setting changes. void reloadAll(); // Rescan the ROM directory for any changes to games and systems. void rescanROMDirectory(); // Navigation. void goToNextGamelist(); void goToPrevGamelist(); void goToGamelist(SystemData* system); void goToSystemView(SystemData* system, bool playTransition); void goToSystem(SystemData* system, bool animate); void goToStart(bool playTransition); void ReloadAndGoToStart(); // Functions to make the GUI behave properly. bool isCameraMoving(); void cancelViewTransitions(); void stopScrolling(); void resetCamera() { if (mCurrentView != nullptr) { mCamera[3].x = -mCurrentView->getPosition().x; mCamera[3].y = -mCurrentView->getPosition().y; } } // Basic video controls. void startViewVideos() override { mCurrentView->startViewVideos(); } void stopViewVideos() override { mCurrentView->stopViewVideos(); } void pauseViewVideos() override { mCurrentView->pauseViewVideos(); } void muteViewVideos() override { mCurrentView->muteViewVideos(); } // Needed on Android to reset the static image delay timer on activity resume. void resetViewVideosTimer() override { if (mCurrentView != nullptr) mCurrentView->resetViewVideosTimer(); } void onFileChanged(FileData* file, bool reloadGamelist); void triggerGameLaunch(FileData* game) { mGameToLaunch = game; mWindow->setBlockInput(true); }; const bool getGameLaunchTriggered() { return (mGameToLaunch != nullptr); } bool input(InputConfig* config, Input input) override; void update(int deltaTime) override; void render(const glm::mat4& parentTrans) override; enum class ViewMode { NOTHING, SYSTEM_SELECT, GAMELIST }; struct State { ViewMode viewing; ViewMode previouslyViewed; SystemData* getSystem() const { assert(viewing == ViewMode::GAMELIST || viewing == ViewMode::SYSTEM_SELECT); return system; } private: friend ViewController; SystemData* system; }; const State& getState() const { return mState; } std::vector getHelpPrompts() override; HelpStyle getHelpStyle() override; HelpStyle getViewHelpStyle(); std::shared_ptr getGamelistView(SystemData* system); std::shared_ptr getSystemListView(); void removeGamelistView(SystemData* system); // Font Awesome symbols. #if defined(_MSC_VER) // MSVC compiler. static inline const std::string ARROW_LEFT_CHAR {Utils::String::wideStringToString(L"\uf104")}; static inline const std::string ARROW_RIGHT_CHAR {Utils::String::wideStringToString(L"\uf105")}; static inline const std::string BRANCH_CHAR {Utils::String::wideStringToString(L"\uf18c")}; static inline const std::string CONTROLLER_CHAR {Utils::String::wideStringToString(L"\uf11b")}; static inline const std::string CROSSEDCIRCLE_CHAR { Utils::String::wideStringToString(L"\uf05e")}; static inline const std::string EXCLAMATION_CHAR {Utils::String::wideStringToString(L"\uf06a")}; static inline const std::string FAVORITE_CHAR {Utils::String::wideStringToString(L"\uf005")}; static inline const std::string FILTER_CHAR {Utils::String::wideStringToString(L"\uf0b0")}; static inline const std::string FOLDER_CHAR {Utils::String::wideStringToString(L"\uf07C")}; static inline const std::string FOLDERLINK_CHAR {Utils::String::wideStringToString(L"\uf090")}; static inline const std::string GEAR_CHAR {Utils::String::wideStringToString(L"\uf013")}; static inline const std::string KEYBOARD_CHAR {Utils::String::wideStringToString(L"\uf11c")}; static inline const std::string TICKMARK_CHAR {Utils::String::wideStringToString(L"\uf14A")}; #else static inline const std::string ARROW_LEFT_CHAR {"\uf104"}; static inline const std::string ARROW_RIGHT_CHAR {"\uf105"}; static inline const std::string BRANCH_CHAR {"\uf18c"}; static inline const std::string CONTROLLER_CHAR {"\uf11b"}; static inline const std::string CROSSEDCIRCLE_CHAR {"\uf05e"}; static inline const std::string EXCLAMATION_CHAR {"\uf06a"}; static inline const std::string FAVORITE_CHAR {"\uf005"}; static inline const std::string FILTER_CHAR {"\uf0b0"}; static inline const std::string FOLDER_CHAR {"\uf07C"}; static inline const std::string FOLDERLINK_CHAR {"\uf090"}; static inline const std::string GEAR_CHAR {"\uf013"}; static inline const std::string KEYBOARD_CHAR {"\uf11c"}; static inline const std::string TICKMARK_CHAR {"\uf14a"}; #endif private: ViewController() noexcept; void launch(FileData* game); Renderer* mRenderer; std::string mNoGamesErrorMessage; std::string mRomDirectory; GuiMsgBox* mNoGamesMessageBox; void playViewTransition(ViewTransition transitionType, bool instant = false); int getSystemId(SystemData* system); // Restore view position if it was moved during wrap around. void restoreViewPosition(); std::shared_ptr mCurrentView; std::shared_ptr mPreviousView; std::shared_ptr mSkipView; std::map> mGamelistViews; std::shared_ptr mSystemListView; ViewTransitionAnimation mLastTransitionAnim; FileData* mGameToLaunch; State mState; glm::mat4 mCamera; bool mSystemViewTransition; bool mWrappedViews; float mWrapPreviousPositionX; float mFadeOpacity; bool mCancelledTransition; // Needed only for the Fade transition style. bool mNextSystem; }; #endif // ES_APP_VIEWS_VIEW_CONTROLLER_H