mirror of
				https://github.com/RetroDECK/ES-DE.git
				synced 2025-04-10 19:15:13 +00:00 
			
		
		
		
	Large refactoring to improve thread safety and improve singleton pattern usage.
This commit is contained in:
		
							parent
							
								
									51bb48b603
								
							
						
					
					
						commit
						254b00a3d8
					
				|  | @ -43,12 +43,8 @@ std::string myCollectionsName = "collections"; | |||
| 
 | ||||
| #define LAST_PLAYED_MAX 50 | ||||
| 
 | ||||
| // Handles the getting, initialization, deinitialization,
 | ||||
| // saving and deletion of a CollectionSystemsManager instance.
 | ||||
| CollectionSystemsManager* CollectionSystemsManager::sInstance = nullptr; | ||||
| 
 | ||||
| CollectionSystemsManager::CollectionSystemsManager(Window* window) | ||||
|     : mWindow(window) | ||||
| CollectionSystemsManager::CollectionSystemsManager() noexcept | ||||
|     : mWindow(Window::getInstance()) | ||||
| { | ||||
|     // clang-format off
 | ||||
|     CollectionSystemDecl systemDecls[] = { | ||||
|  | @ -92,8 +88,6 @@ CollectionSystemsManager::CollectionSystemsManager(Window* window) | |||
| 
 | ||||
| CollectionSystemsManager::~CollectionSystemsManager() | ||||
| { | ||||
|     assert(sInstance == this); | ||||
| 
 | ||||
|     // Don't attempt to remove any collections if no systems exist.
 | ||||
|     if (SystemData::sSystemVector.size() > 0) | ||||
|         removeCollectionsFromDisplayedSystems(); | ||||
|  | @ -114,25 +108,12 @@ CollectionSystemsManager::~CollectionSystemsManager() | |||
|         delete (*it).second.system; | ||||
| 
 | ||||
|     delete mCollectionEnvData; | ||||
|     sInstance = nullptr; | ||||
| } | ||||
| 
 | ||||
| CollectionSystemsManager* CollectionSystemsManager::get() | ||||
| CollectionSystemsManager* CollectionSystemsManager::getInstance() | ||||
| { | ||||
|     assert(sInstance); | ||||
|     return sInstance; | ||||
| } | ||||
| 
 | ||||
| void CollectionSystemsManager::init(Window* window) | ||||
| { | ||||
|     assert(!sInstance); | ||||
|     sInstance = new CollectionSystemsManager(window); | ||||
| } | ||||
| 
 | ||||
| void CollectionSystemsManager::deinit() | ||||
| { | ||||
|     if (sInstance) | ||||
|         delete sInstance; | ||||
|     static CollectionSystemsManager instance; | ||||
|     return &instance; | ||||
| } | ||||
| 
 | ||||
| void CollectionSystemsManager::saveCustomCollection(SystemData* sys) | ||||
|  | @ -927,8 +908,8 @@ void CollectionSystemsManager::deleteCustomCollection(const std::string& collect | |||
|         delete mWindow->peekGui(); | ||||
| 
 | ||||
|     if (collectionEntry != mCustomCollectionSystemsData.end()) { | ||||
|         CollectionSystemsManager::get()->loadEnabledListFromSettings(); | ||||
|         CollectionSystemsManager::get()->updateSystemsList(); | ||||
|         CollectionSystemsManager::getInstance()->loadEnabledListFromSettings(); | ||||
|         CollectionSystemsManager::getInstance()->updateSystemsList(); | ||||
| 
 | ||||
|         ViewController::get()->removeGameListView(collectionEntry->second.system); | ||||
|         ViewController::get()->reloadAll(); | ||||
|  |  | |||
|  | @ -72,12 +72,7 @@ struct stringComparator { | |||
| class CollectionSystemsManager | ||||
| { | ||||
| public: | ||||
|     CollectionSystemsManager(Window* window); | ||||
|     ~CollectionSystemsManager(); | ||||
| 
 | ||||
|     static CollectionSystemsManager* get(); | ||||
|     static void init(Window* window); | ||||
|     static void deinit(); | ||||
|     static CollectionSystemsManager* getInstance(); | ||||
|     void saveCustomCollection(SystemData* sys); | ||||
| 
 | ||||
|     // Functions to load all collections into memory, and enable the active ones:
 | ||||
|  | @ -137,7 +132,9 @@ public: | |||
|     const std::string& getEditingCollection() const { return mEditingCollection; } | ||||
| 
 | ||||
| private: | ||||
|     static CollectionSystemsManager* sInstance; | ||||
|     CollectionSystemsManager() noexcept; | ||||
|     ~CollectionSystemsManager(); | ||||
| 
 | ||||
|     SystemEnvironmentData* mCollectionEnvData; | ||||
|     std::map<std::string, CollectionSystemDecl, stringComparator> mCollectionSystemDeclsIndex; | ||||
|     std::map<std::string, CollectionSystemData, stringComparator> mAutoCollectionSystemsData; | ||||
|  |  | |||
|  | @ -1166,7 +1166,7 @@ void FileData::launchGame(Window* window) | |||
|                                                 gameToUpdate->metadata.get("lastplayed")); | ||||
|     } | ||||
| 
 | ||||
|     CollectionSystemsManager::get()->refreshCollectionSystems(gameToUpdate); | ||||
|     CollectionSystemsManager::getInstance()->refreshCollectionSystems(gameToUpdate); | ||||
| 
 | ||||
|     gameToUpdate->mSystem->onMetaDataSavePoint(); | ||||
| } | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ | |||
| #include "components/VideoFFmpegComponent.h" | ||||
| #include "views/ViewController.h" | ||||
| 
 | ||||
| MediaViewer::MediaViewer(Window* window) | ||||
|     : mWindow(window) | ||||
| MediaViewer::MediaViewer() | ||||
|     : mWindow(Window::getInstance()) | ||||
|     , mVideo(nullptr) | ||||
|     , mImage(nullptr) | ||||
| { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| class MediaViewer : public Window::MediaViewer | ||||
| { | ||||
| public: | ||||
|     MediaViewer(Window* window); | ||||
|     MediaViewer(); | ||||
|     virtual ~MediaViewer(); | ||||
| 
 | ||||
|     virtual bool startMediaViewer(FileData* game) override; | ||||
|  |  | |||
|  | @ -51,14 +51,14 @@ void FindRules::loadFindRules() | |||
|     } | ||||
|     else { | ||||
| #if defined(_WIN64) | ||||
|         path = ResourceManager::getInstance()->getResourcePath( | ||||
|             ":/systems/windows/es_find_rules.xml", false); | ||||
|         path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_find_rules.xml", | ||||
|                                                               false); | ||||
| #elif defined(__APPLE__) | ||||
|         path = ResourceManager::getInstance()->getResourcePath(":/systems/macos/es_find_rules.xml", | ||||
|                                                                false); | ||||
|         path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_find_rules.xml", | ||||
|                                                               false); | ||||
| #else | ||||
|         path = ResourceManager::getInstance()->getResourcePath(":/systems/unix/es_find_rules.xml", | ||||
|                                                                false); | ||||
|         path = ResourceManager::getInstance().getResourcePath(":/systems/unix/es_find_rules.xml", | ||||
|                                                               false); | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|  | @ -659,7 +659,7 @@ bool SystemData::loadConfig() | |||
| 
 | ||||
|     // Don't load any collections if there are no systems available.
 | ||||
|     if (sSystemVector.size() > 0) | ||||
|         CollectionSystemsManager::get()->loadCollectionSystems(); | ||||
|         CollectionSystemsManager::getInstance()->loadCollectionSystems(); | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
|  | @ -718,12 +718,11 @@ std::vector<std::string> SystemData::getConfigPath(bool legacyWarning) | |||
|     } | ||||
| 
 | ||||
| #if defined(_WIN64) | ||||
|     path = | ||||
|         ResourceManager::getInstance()->getResourcePath(":/systems/windows/es_systems.xml", true); | ||||
|     path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_systems.xml", true); | ||||
| #elif defined(__APPLE__) | ||||
|     path = ResourceManager::getInstance()->getResourcePath(":/systems/macos/es_systems.xml", true); | ||||
|     path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_systems.xml", true); | ||||
| #else | ||||
|     path = ResourceManager::getInstance()->getResourcePath(":/systems/unix/es_systems.xml", true); | ||||
|     path = ResourceManager::getInstance().getResourcePath(":/systems/unix/es_systems.xml", true); | ||||
| #endif | ||||
| 
 | ||||
|     paths.push_back(path); | ||||
|  |  | |||
|  | @ -29,8 +29,8 @@ | |||
| 
 | ||||
| #define FADE_TIME 300 | ||||
| 
 | ||||
| SystemScreensaver::SystemScreensaver(Window* window) | ||||
|     : mWindow(window) | ||||
| SystemScreensaver::SystemScreensaver() | ||||
|     : mWindow(Window::getInstance()) | ||||
|     , mState(STATE_INACTIVE) | ||||
|     , mImageScreensaver(nullptr) | ||||
|     , mVideoScreensaver(nullptr) | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class VideoComponent; | |||
| class SystemScreensaver : public Window::Screensaver | ||||
| { | ||||
| public: | ||||
|     SystemScreensaver(Window* window); | ||||
|     SystemScreensaver(); | ||||
|     virtual ~SystemScreensaver(); | ||||
| 
 | ||||
|     virtual bool allowSleep() | ||||
|  |  | |||
|  | @ -20,8 +20,6 @@ std::string VolumeControl::mixerName = "Master"; | |||
| std::string VolumeControl::mixerCard = "default"; | ||||
| #endif | ||||
| 
 | ||||
| VolumeControl* VolumeControl::sInstance = nullptr; | ||||
| 
 | ||||
| VolumeControl::VolumeControl() | ||||
| #if defined(__linux__) | ||||
|     : mixerIndex(0) | ||||
|  | @ -44,23 +42,6 @@ VolumeControl::~VolumeControl() | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| VolumeControl* VolumeControl::getInstance() | ||||
| { | ||||
|     // Check if a VolumeControl instance is already created, and if not then create it.
 | ||||
|     if (!sInstance) | ||||
|         sInstance = new VolumeControl(); | ||||
| 
 | ||||
|     return sInstance; | ||||
| } | ||||
| 
 | ||||
| void VolumeControl::deleteInstance() | ||||
| { | ||||
|     if (sInstance) { | ||||
|         delete sInstance; | ||||
|         sInstance = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void VolumeControl::init() | ||||
| { | ||||
|     // Initialize audio mixer interface.
 | ||||
|  |  | |||
|  | @ -27,17 +27,12 @@ public: | |||
|     VolumeControl(); | ||||
|     ~VolumeControl(); | ||||
| 
 | ||||
|     static VolumeControl* getInstance(); | ||||
|     void deleteInstance(); | ||||
| 
 | ||||
|     void init(); | ||||
|     void deinit(); | ||||
| 
 | ||||
|     int getVolume() const; | ||||
|     void setVolume(int volume); | ||||
| 
 | ||||
|     static VolumeControl* sInstance; | ||||
| 
 | ||||
| #if defined(__linux__) | ||||
|     static std::string mixerName; | ||||
|     static std::string mixerCard; | ||||
|  |  | |||
|  | @ -25,18 +25,19 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|     , mDeletedCustomCollection(false) | ||||
| { | ||||
|     // Finish editing custom collection.
 | ||||
|     if (CollectionSystemsManager::get()->isEditing()) { | ||||
|     if (CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|         ComponentListRow row; | ||||
|         row.addElement(std::make_shared<TextComponent>( | ||||
|                            mWindow, | ||||
|                            "FINISH EDITING '" + | ||||
|                                Utils::String::toUpper( | ||||
|                                    CollectionSystemsManager::get()->getEditingCollection()) + | ||||
|                                "' COLLECTION", | ||||
|                            Font::get(FONT_SIZE_MEDIUM), 0x777777FF), | ||||
|                        true); | ||||
|         row.addElement( | ||||
|             std::make_shared<TextComponent>( | ||||
|                 mWindow, | ||||
|                 "FINISH EDITING '" + | ||||
|                     Utils::String::toUpper( | ||||
|                         CollectionSystemsManager::getInstance()->getEditingCollection()) + | ||||
|                     "' COLLECTION", | ||||
|                 Font::get(FONT_SIZE_MEDIUM), 0x777777FF), | ||||
|             true); | ||||
|         row.makeAcceptInputHandler([this] { | ||||
|             CollectionSystemsManager::get()->exitEditMode(); | ||||
|             CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|             mWindow->invalidateCachedBackground(); | ||||
|             delete this; | ||||
|         }); | ||||
|  | @ -47,7 +48,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|     collection_systems_auto = std::make_shared<OptionListComponent<std::string>>( | ||||
|         mWindow, getHelpStyle(), "SELECT COLLECTIONS", true); | ||||
|     std::map<std::string, CollectionSystemData, stringComparator> autoSystems = | ||||
|         CollectionSystemsManager::get()->getAutoCollectionSystems(); | ||||
|         CollectionSystemsManager::getInstance()->getAutoCollectionSystems(); | ||||
|     // Add automatic systems.
 | ||||
|     for (std::map<std::string, CollectionSystemData, stringComparator>::const_iterator it = | ||||
|              autoSystems.cbegin(); | ||||
|  | @ -60,8 +61,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|             collection_systems_auto->getSelectedObjects(), ",", true); | ||||
|         std::string autoSystemsConfig = Settings::getInstance()->getString("CollectionSystemsAuto"); | ||||
|         if (autoSystemsSelected != autoSystemsConfig) { | ||||
|             if (CollectionSystemsManager::get()->isEditing()) | ||||
|                 CollectionSystemsManager::get()->exitEditMode(); | ||||
|             if (CollectionSystemsManager::getInstance()->isEditing()) | ||||
|                 CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|             Settings::getInstance()->setString("CollectionSystemsAuto", autoSystemsSelected); | ||||
|             // Check if any systems have been enabled, and if so repopulate them, which results in
 | ||||
|             // a complete initialization of their content. This is necessary as collections aren't
 | ||||
|  | @ -83,7 +84,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|             } | ||||
|             if (!addedAutoSystems.empty()) { | ||||
|                 for (std::string system : addedAutoSystems) | ||||
|                     CollectionSystemsManager::get()->repopulateCollection( | ||||
|                     CollectionSystemsManager::getInstance()->repopulateCollection( | ||||
|                         autoSystems.find(system)->second.system); | ||||
|             } | ||||
|             setNeedsSaving(); | ||||
|  | @ -96,7 +97,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|     collection_systems_custom = std::make_shared<OptionListComponent<std::string>>( | ||||
|         mWindow, getHelpStyle(), "SELECT COLLECTIONS", true); | ||||
|     std::map<std::string, CollectionSystemData, stringComparator> customSystems = | ||||
|         CollectionSystemsManager::get()->getCustomCollectionSystems(); | ||||
|         CollectionSystemsManager::getInstance()->getCustomCollectionSystems(); | ||||
|     // Add custom systems.
 | ||||
|     for (std::map<std::string, CollectionSystemData, stringComparator>::const_iterator it = | ||||
|              customSystems.cbegin(); | ||||
|  | @ -112,8 +113,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|             std::string customSystemsConfig = | ||||
|                 Settings::getInstance()->getString("CollectionSystemsCustom"); | ||||
|             if (customSystemsSelected != customSystemsConfig) { | ||||
|                 if (CollectionSystemsManager::get()->isEditing()) | ||||
|                     CollectionSystemsManager::get()->exitEditMode(); | ||||
|                 if (CollectionSystemsManager::getInstance()->isEditing()) | ||||
|                     CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|                 Settings::getInstance()->setString("CollectionSystemsCustom", | ||||
|                                                    customSystemsSelected); | ||||
|                 // Check if any systems have been enabled, and if so repopulate them, which
 | ||||
|  | @ -137,7 +138,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|                 } | ||||
|                 if (!mAddedCustomCollection && !addedCustomSystems.empty()) { | ||||
|                     for (std::string system : addedCustomSystems) | ||||
|                         CollectionSystemsManager::get()->repopulateCollection( | ||||
|                         CollectionSystemsManager::getInstance()->repopulateCollection( | ||||
|                             customSystems.find(system)->second.system); | ||||
|                 } | ||||
|                 setNeedsSaving(); | ||||
|  | @ -159,7 +160,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
| 
 | ||||
|     // Create custom collection from theme.
 | ||||
|     std::vector<std::string> unusedFolders = | ||||
|         CollectionSystemsManager::get()->getUnusedSystemsFromTheme(); | ||||
|         CollectionSystemsManager::getInstance()->getUnusedSystemsFromTheme(); | ||||
|     if (unusedFolders.size() > 0) { | ||||
|         ComponentListRow row; | ||||
|         auto themeCollection = | ||||
|  | @ -259,8 +260,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|                         "ARE YOU SURE?", | ||||
|                     "YES", | ||||
|                     [this, name] { | ||||
|                         if (CollectionSystemsManager::get()->isEditing()) | ||||
|                             CollectionSystemsManager::get()->exitEditMode(); | ||||
|                         if (CollectionSystemsManager::getInstance()->isEditing()) | ||||
|                             CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|                         mDeletedCustomCollection = true; | ||||
|                         std::vector<std::string> selectedCustomCollections = | ||||
|                             collection_systems_custom->getSelectedObjects(); | ||||
|  | @ -289,7 +290,7 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|                             setNeedsSaving(); | ||||
|                             setNeedsGoToStart(); | ||||
|                         } | ||||
|                         CollectionSystemsManager::get()->deleteCustomCollection(name); | ||||
|                         CollectionSystemsManager::getInstance()->deleteCustomCollection(name); | ||||
|                         return true; | ||||
|                     }, | ||||
|                     "NO", [] { return false; })); | ||||
|  | @ -349,8 +350,8 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
|             Settings::getInstance()->getBool("UseCustomCollectionsSystem")) { | ||||
|             Settings::getInstance()->setBool("UseCustomCollectionsSystem", | ||||
|                                              use_custom_collections_system->getState()); | ||||
|             if (CollectionSystemsManager::get()->isEditing()) | ||||
|                 CollectionSystemsManager::get()->exitEditMode(); | ||||
|             if (CollectionSystemsManager::getInstance()->isEditing()) | ||||
|                 CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|             setNeedsSaving(); | ||||
|             setNeedsCollectionsUpdate(); | ||||
|             setNeedsReloading(); | ||||
|  | @ -378,14 +379,15 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st | |||
| 
 | ||||
| void GuiCollectionSystemsOptions::createCustomCollection(std::string inName) | ||||
| { | ||||
|     if (CollectionSystemsManager::get()->isEditing()) | ||||
|         CollectionSystemsManager::get()->exitEditMode(); | ||||
|     if (CollectionSystemsManager::getInstance()->isEditing()) | ||||
|         CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
| 
 | ||||
|     std::string collectionName = CollectionSystemsManager::get()->getValidNewCollectionName(inName); | ||||
|     std::string collectionName = | ||||
|         CollectionSystemsManager::getInstance()->getValidNewCollectionName(inName); | ||||
|     SystemData* newCollection = | ||||
|         CollectionSystemsManager::get()->addNewCustomCollection(collectionName); | ||||
|         CollectionSystemsManager::getInstance()->addNewCustomCollection(collectionName); | ||||
| 
 | ||||
|     CollectionSystemsManager::get()->saveCustomCollection(newCollection); | ||||
|     CollectionSystemsManager::getInstance()->saveCustomCollection(newCollection); | ||||
|     collection_systems_custom->add(collectionName, collectionName, true); | ||||
| 
 | ||||
|     mAddedCustomCollection = true; | ||||
|  | @ -399,5 +401,5 @@ void GuiCollectionSystemsOptions::createCustomCollection(std::string inName) | |||
|     Window* window = mWindow; | ||||
|     while (window->peekGui() && window->peekGui() != ViewController::get()) | ||||
|         delete window->peekGui(); | ||||
|     CollectionSystemsManager::get()->setEditMode(collectionName); | ||||
|     CollectionSystemsManager::getInstance()->setEditMode(collectionName); | ||||
| } | ||||
|  |  | |||
|  | @ -161,7 +161,7 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) | |||
|         } | ||||
|     } | ||||
|     // Add a dummy entry when applicable as the menu looks quite ugly if it's just blank.
 | ||||
|     else if (!CollectionSystemsManager::get()->isEditing() && | ||||
|     else if (!CollectionSystemsManager::getInstance()->isEditing() && | ||||
|              mSystem->getRootFolder()->getChildren().size() == 0 && !mIsCustomCollectionGroup && | ||||
|              !mIsCustomCollection) { | ||||
|         row.elements.clear(); | ||||
|  | @ -179,7 +179,7 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) | |||
| 
 | ||||
|     if (UIModeController::getInstance()->isUIModeFull() && | ||||
|         (mIsCustomCollection || mIsCustomCollectionGroup)) { | ||||
|         if (CollectionSystemsManager::get()->getEditingCollection() != customSystem) { | ||||
|         if (CollectionSystemsManager::getInstance()->getEditingCollection() != customSystem) { | ||||
|             row.elements.clear(); | ||||
|             row.addElement(std::make_shared<TextComponent>(mWindow, | ||||
|                                                            "ADD/REMOVE GAMES TO THIS COLLECTION", | ||||
|  | @ -191,16 +191,17 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) | |||
|     } | ||||
| 
 | ||||
|     if (UIModeController::getInstance()->isUIModeFull() && | ||||
|         CollectionSystemsManager::get()->isEditing()) { | ||||
|         CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|         row.elements.clear(); | ||||
|         row.addElement(std::make_shared<TextComponent>( | ||||
|                            mWindow, | ||||
|                            "FINISH EDITING '" + | ||||
|                                Utils::String::toUpper( | ||||
|                                    CollectionSystemsManager::get()->getEditingCollection()) + | ||||
|                                "' COLLECTION", | ||||
|                            Font::get(FONT_SIZE_MEDIUM), 0x777777FF), | ||||
|                        true); | ||||
|         row.addElement( | ||||
|             std::make_shared<TextComponent>( | ||||
|                 mWindow, | ||||
|                 "FINISH EDITING '" + | ||||
|                     Utils::String::toUpper( | ||||
|                         CollectionSystemsManager::getInstance()->getEditingCollection()) + | ||||
|                     "' COLLECTION", | ||||
|                 Font::get(FONT_SIZE_MEDIUM), 0x777777FF), | ||||
|             true); | ||||
|         row.makeAcceptInputHandler(std::bind(&GuiGamelistOptions::exitEditMode, this)); | ||||
|         mMenu.addRow(row); | ||||
|     } | ||||
|  | @ -336,7 +337,8 @@ void GuiGamelistOptions::startEditMode() | |||
|     std::string editingSystem = mSystem->getName(); | ||||
|     // Need to check if we're editing the collections bundle,
 | ||||
|     // as we will want to edit the selected collection within.
 | ||||
|     if (editingSystem == CollectionSystemsManager::get()->getCustomCollectionsBundle()->getName()) { | ||||
|     if (editingSystem == | ||||
|         CollectionSystemsManager::getInstance()->getCustomCollectionsBundle()->getName()) { | ||||
|         FileData* file = getGamelist()->getCursor(); | ||||
|         // Do we have the cursor on a specific collection?.
 | ||||
|         if (file->getType() == FOLDER) | ||||
|  | @ -345,7 +347,7 @@ void GuiGamelistOptions::startEditMode() | |||
|             // We are inside a specific collection. We want to edit that one.
 | ||||
|             editingSystem = file->getSystem()->getName(); | ||||
|     } | ||||
|     CollectionSystemsManager::get()->setEditMode(editingSystem); | ||||
|     CollectionSystemsManager::getInstance()->setEditMode(editingSystem); | ||||
| 
 | ||||
|     // Display the indication icons which show what games are part of the custom collection
 | ||||
|     // currently being edited. This is done cheaply using onFileChanged() which will trigger
 | ||||
|  | @ -362,7 +364,7 @@ void GuiGamelistOptions::startEditMode() | |||
| 
 | ||||
| void GuiGamelistOptions::exitEditMode() | ||||
| { | ||||
|     CollectionSystemsManager::get()->exitEditMode(); | ||||
|     CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|     if (mSystem->getRootFolder()->getChildren().size() == 0) | ||||
|         NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); | ||||
|     delete this; | ||||
|  | @ -420,7 +422,7 @@ void GuiGamelistOptions::openMetaDataEd() | |||
| 
 | ||||
|         // Update all collections where the game is present.
 | ||||
|         if (file->getType() == GAME) | ||||
|             CollectionSystemsManager::get()->refreshCollectionSystems(file, true); | ||||
|             CollectionSystemsManager::getInstance()->refreshCollectionSystems(file, true); | ||||
| 
 | ||||
|         file->getSystem()->sortSystem(); | ||||
|         // This delay reduces the likelyhood that the SVG rasterizer which is running in a
 | ||||
|  | @ -440,7 +442,7 @@ void GuiGamelistOptions::openMetaDataEd() | |||
|     deleteGameBtnFunc = [this, file] { | ||||
|         LOG(LogInfo) << "Deleting the game file \"" << file->getFullPath() | ||||
|                      << "\", all its media files and its gamelist.xml entry."; | ||||
|         CollectionSystemsManager::get()->deleteCollectionFiles(file); | ||||
|         CollectionSystemsManager::getInstance()->deleteCollectionFiles(file); | ||||
|         ViewController::get()->getGameListView(file->getSystem()).get()->removeMedia(file); | ||||
|         ViewController::get()->getGameListView(file->getSystem()).get()->remove(file, true); | ||||
|         mSystem->getRootFolder()->sort(*mListSort->getSelected(), mFavoritesSorting); | ||||
|  | @ -551,7 +553,7 @@ std::vector<HelpPrompt> GuiGamelistOptions::getHelpPrompts() | |||
| { | ||||
|     auto prompts = mMenu.getHelpPrompts(); | ||||
|     if (mSystem->getRootFolder()->getChildren().size() > 0 || mIsCustomCollectionGroup || | ||||
|         mIsCustomCollection || CollectionSystemsManager::get()->isEditing()) | ||||
|         mIsCustomCollection || CollectionSystemsManager::getInstance()->isEditing()) | ||||
|         prompts.push_back(HelpPrompt("a", "select")); | ||||
|     if (mSystem->getRootFolder()->getChildren().size() > 0 && mSystem->getName() != "recent") { | ||||
|         prompts.push_back(HelpPrompt("b", "close (apply)")); | ||||
|  |  | |||
|  | @ -14,10 +14,10 @@ | |||
| #include "components/TextComponent.h" | ||||
| #include "utils/StringUtil.h" | ||||
| 
 | ||||
| GuiLaunchScreen::GuiLaunchScreen(Window* window) | ||||
|     : GuiComponent(window) | ||||
|     , mWindow(window) | ||||
|     , mBackground(window, ":/graphics/frame.svg") | ||||
| GuiLaunchScreen::GuiLaunchScreen() | ||||
|     : GuiComponent(Window::getInstance()) | ||||
|     , mWindow(Window::getInstance()) | ||||
|     , mBackground(mWindow, ":/graphics/frame.svg") | ||||
|     , mGrid(nullptr) | ||||
|     , mMarquee(nullptr) | ||||
| { | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ class FileData; | |||
| class GuiLaunchScreen : public Window::GuiLaunchScreen, GuiComponent | ||||
| { | ||||
| public: | ||||
|     GuiLaunchScreen(Window* window); | ||||
|     GuiLaunchScreen(); | ||||
|     virtual ~GuiLaunchScreen(); | ||||
| 
 | ||||
|     virtual void displayLaunchScreen(FileData* game) override; | ||||
|  |  | |||
|  | @ -189,12 +189,12 @@ void GuiMenu::openUIOptions() | |||
|                 Scripting::fireEvent("theme-changed", theme_set->getSelected(), | ||||
|                                      Settings::getInstance()->getString("ThemeSet")); | ||||
|                 Settings::getInstance()->setString("ThemeSet", theme_set->getSelected()); | ||||
|                 CollectionSystemsManager::get()->updateSystemsList(); | ||||
|                 CollectionSystemsManager::getInstance()->updateSystemsList(); | ||||
|                 mWindow->setChangedThemeSet(); | ||||
|                 // This is required so that the custom collection system does not disappear
 | ||||
|                 // if the user is editing a custom collection when switching theme sets.
 | ||||
|                 if (CollectionSystemsManager::get()->isEditing()) { | ||||
|                     CollectionSystemsManager::get()->exitEditMode(); | ||||
|                 if (CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|                     CollectionSystemsManager::getInstance()->exitEditMode(); | ||||
|                     s->setNeedsCollectionsUpdate(); | ||||
|                 } | ||||
|                 s->setNeedsSaving(); | ||||
|  | @ -609,16 +609,22 @@ void GuiMenu::openSoundOptions() | |||
| // implemented for these operating systems.
 | ||||
| #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) | ||||
|     // System volume.
 | ||||
|     auto system_volume = std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%"); | ||||
|     system_volume->setValue(static_cast<float>(VolumeControl::getInstance()->getVolume())); | ||||
|     s->addWithLabel("SYSTEM VOLUME", system_volume); | ||||
|     s->addSaveFunc([system_volume] { | ||||
|         VolumeControl::getInstance()->setVolume( | ||||
|             static_cast<int>(std::round(system_volume->getValue()))); | ||||
|         // Explicitly delete the VolumeControl instance so that it will reinitialize the
 | ||||
|         // next time the menu is entered. This is the easiest way to detect new default
 | ||||
|         // audio devices or changes to the audio volume done by the operating system.
 | ||||
|         VolumeControl::getInstance()->deleteInstance(); | ||||
|     // The reason to create the VolumeControl object every time instead of making it a singleton
 | ||||
|     // is that this is the easiest way to detect new default audio devices or changes to the
 | ||||
|     // audio volume done by the operating system. And we don't really need this object laying
 | ||||
|     // around anyway as it's only used here.
 | ||||
|     VolumeControl volumeControl; | ||||
|     int currentVolume = volumeControl.getVolume(); | ||||
| 
 | ||||
|     auto systemVolume = std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%"); | ||||
|     systemVolume->setValue(static_cast<float>(currentVolume)); | ||||
|     s->addWithLabel("SYSTEM VOLUME", systemVolume); | ||||
|     s->addSaveFunc([systemVolume, currentVolume] { | ||||
|         // No need to create the VolumeControl object unless the volume has actually been changed.
 | ||||
|         if (static_cast<int>(systemVolume->getValue()) != currentVolume) { | ||||
|             VolumeControl volumeControl; | ||||
|             volumeControl.setVolume(static_cast<int>(std::round(systemVolume->getValue()))); | ||||
|         } | ||||
|     }); | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -689,7 +689,7 @@ void GuiMetaDataEd::save() | |||
|                 // Update disabled auto collections when hiding a game, as otherwise these could
 | ||||
|                 // get invalid gamelist cursor positions. A cursor pointing to a removed game
 | ||||
|                 // would crash the application upon enabling the collections.
 | ||||
|                 CollectionSystemsManager::get()->refreshCollectionSystems(hideGame, true); | ||||
|                 CollectionSystemsManager::getInstance()->refreshCollectionSystems(hideGame, true); | ||||
|                 // Remove the game from the index of all systems.
 | ||||
|                 for (SystemData* sys : SystemData::sSystemVector) { | ||||
|                     std::vector<FileData*> children; | ||||
|  | @ -706,13 +706,14 @@ void GuiMetaDataEd::save() | |||
|     } | ||||
|     else { | ||||
|         // Update all collections where the game is present.
 | ||||
|         CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game); | ||||
|         CollectionSystemsManager::getInstance()->refreshCollectionSystems(mScraperParams.game); | ||||
|     } | ||||
| 
 | ||||
|     // If game counting was re-enabled for the game, then reactivate it in any custom collections
 | ||||
|     // where it may exist.
 | ||||
|     if (setGameAsCounted) | ||||
|         CollectionSystemsManager::get()->reactivateCustomCollectionEntry(mScraperParams.game); | ||||
|         CollectionSystemsManager::getInstance()->reactivateCustomCollectionEntry( | ||||
|             mScraperParams.game); | ||||
| 
 | ||||
|     mScraperParams.system->onMetaDataSavePoint(); | ||||
| 
 | ||||
|  | @ -812,7 +813,7 @@ void GuiMetaDataEd::close() | |||
|             TextureResource::manualUnload(mScraperParams.game->getMarqueePath(), false); | ||||
|             ViewController::get()->reloadGameListView(mScraperParams.system); | ||||
|             // Update all collections where the game is present.
 | ||||
|             CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game); | ||||
|             CollectionSystemsManager::getInstance()->refreshCollectionSystems(mScraperParams.game); | ||||
|             mWindow->invalidateCachedBackground(); | ||||
|         } | ||||
|         ViewController::get()->onPauseVideo(); | ||||
|  |  | |||
|  | @ -280,7 +280,7 @@ void GuiScraperMulti::acceptResult(const ScraperSearchResult& result) | |||
|     mSearchQueue.pop(); | ||||
|     ++mCurrentGame; | ||||
|     ++mTotalSuccessful; | ||||
|     CollectionSystemsManager::get()->refreshCollectionSystems(search.game); | ||||
|     CollectionSystemsManager::getInstance()->refreshCollectionSystems(search.game); | ||||
|     doNextSearch(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -66,8 +66,8 @@ void GuiSettings::save() | |||
|         mWindow->reloadHelpPrompts(); | ||||
| 
 | ||||
|     if (mNeedsCollectionsUpdate) { | ||||
|         CollectionSystemsManager::get()->loadEnabledListFromSettings(); | ||||
|         CollectionSystemsManager::get()->updateSystemsList(); | ||||
|         CollectionSystemsManager::getInstance()->loadEnabledListFromSettings(); | ||||
|         CollectionSystemsManager::getInstance()->updateSystemsList(); | ||||
|     } | ||||
| 
 | ||||
|     if (mNeedsSorting) { | ||||
|  |  | |||
|  | @ -528,24 +528,27 @@ int main(int argc, char* argv[]) | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Window window; | ||||
|     SystemScreensaver screensaver(&window); | ||||
|     MediaViewer mediaViewer(&window); | ||||
|     GuiLaunchScreen guiLaunchScreen(&window); | ||||
|     ViewController::init(&window); | ||||
|     CollectionSystemsManager::init(&window); | ||||
|     window.pushGui(ViewController::get()); | ||||
|     Window* window = Window::getInstance(); | ||||
| 
 | ||||
|     ViewController::get(); | ||||
|     CollectionSystemsManager::getInstance(); | ||||
| 
 | ||||
|     SystemScreensaver screensaver; | ||||
|     MediaViewer mediaViewer; | ||||
|     GuiLaunchScreen guiLaunchScreen; | ||||
| 
 | ||||
|     if (!window->init()) { | ||||
|         LOG(LogError) << "Window failed to initialize"; | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     window->pushGui(ViewController::get()); | ||||
| 
 | ||||
|     bool splashScreen = Settings::getInstance()->getBool("SplashScreen"); | ||||
|     bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress"); | ||||
|     SDL_Event event{}; | ||||
| 
 | ||||
|     if (!window.init()) { | ||||
|         LOG(LogError) << "Window failed to initialize"; | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     InputManager::getInstance()->parseEvent(event, &window); | ||||
|     InputManager::getInstance().parseEvent(event, window); | ||||
|     if (event.type == SDL_QUIT) | ||||
|         return 1; | ||||
| 
 | ||||
|  | @ -571,7 +574,7 @@ int main(int argc, char* argv[]) | |||
|         std::string progressText = "Loading..."; | ||||
|         if (splashScreenProgress) | ||||
|             progressText = "Loading system config..."; | ||||
|         window.renderLoadingScreen(progressText); | ||||
|         window->renderLoadingScreen(progressText); | ||||
|     } | ||||
| 
 | ||||
|     AudioManager::getInstance(); | ||||
|  | @ -609,13 +612,13 @@ int main(int argc, char* argv[]) | |||
|     ViewController::get()->preload(); | ||||
| 
 | ||||
|     if (splashScreen && splashScreenProgress) | ||||
|         window.renderLoadingScreen("Done"); | ||||
|         window->renderLoadingScreen("Done"); | ||||
| 
 | ||||
|     // Open the input configuration GUI if the flag to force this was passed from the command line.
 | ||||
|     if (!loadSystemsStatus) { | ||||
|         if (forceInputConfig) { | ||||
|             window.pushGui(new GuiDetectDevice(&window, false, true, | ||||
|                                                [] { ViewController::get()->goToStart(true); })); | ||||
|             window->pushGui(new GuiDetectDevice(window, false, true, | ||||
|                                                 [] { ViewController::get()->goToStart(true); })); | ||||
|         } | ||||
|         else { | ||||
|             ViewController::get()->goToStart(true); | ||||
|  | @ -645,7 +648,7 @@ int main(int argc, char* argv[]) | |||
|     while (running) { | ||||
|         if (SDL_PollEvent(&event)) { | ||||
|             do { | ||||
|                 InputManager::getInstance()->parseEvent(event, &window); | ||||
|                 InputManager::getInstance().parseEvent(event, window); | ||||
| 
 | ||||
|                 if (event.type == SDL_QUIT) | ||||
|                     running = false; | ||||
|  | @ -653,7 +656,7 @@ int main(int argc, char* argv[]) | |||
|             } while (SDL_PollEvent(&event)); | ||||
|         } | ||||
| 
 | ||||
|         if (window.isSleeping()) { | ||||
|         if (window->isSleeping()) { | ||||
|             lastTime = SDL_GetTicks(); | ||||
|             // This doesn't need to be accurate, we're just giving up
 | ||||
|             // our CPU time until something wakes us up.
 | ||||
|  | @ -669,18 +672,17 @@ int main(int argc, char* argv[]) | |||
|         if (deltaTime < 0) | ||||
|             deltaTime = 1000; | ||||
| 
 | ||||
|         window.update(deltaTime); | ||||
|         window.render(); | ||||
|         window->update(deltaTime); | ||||
|         window->render(); | ||||
|         Renderer::swapBuffers(); | ||||
| 
 | ||||
|         Log::flush(); | ||||
|     } | ||||
| 
 | ||||
|     while (window.peekGui() != ViewController::get()) | ||||
|         delete window.peekGui(); | ||||
|     window.deinit(); | ||||
|     while (window->peekGui() != ViewController::get()) | ||||
|         delete window->peekGui(); | ||||
|     window->deinit(); | ||||
| 
 | ||||
|     CollectionSystemsManager::deinit(); | ||||
|     SystemData::deleteSystems(); | ||||
|     NavigationSounds::getInstance().deinit(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -77,9 +77,9 @@ void SystemView::populate() | |||
|                 auto path = logoElem->get<std::string>("path"); | ||||
|                 std::string defaultPath = | ||||
|                     logoElem->has("default") ? logoElem->get<std::string>("default") : ""; | ||||
|                 if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) || | ||||
|                 if ((!path.empty() && ResourceManager::getInstance().fileExists(path)) || | ||||
|                     (!defaultPath.empty() && | ||||
|                      ResourceManager::getInstance()->fileExists(defaultPath))) { | ||||
|                      ResourceManager::getInstance().fileExists(defaultPath))) { | ||||
|                     auto* logo = new ImageComponent(mWindow, false, false); | ||||
|                     logo->setMaxSize(glm::round(mCarousel.logoSize * mCarousel.logoScale)); | ||||
|                     logo->applyTheme(theme, "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR); | ||||
|  | @ -101,9 +101,9 @@ void SystemView::populate() | |||
|                     auto path = logoElem->get<std::string>("path"); | ||||
|                     std::string defaultPath = | ||||
|                         logoElem->has("default") ? logoElem->get<std::string>("default") : ""; | ||||
|                     if ((!path.empty() && ResourceManager::getInstance()->fileExists(path)) || | ||||
|                     if ((!path.empty() && ResourceManager::getInstance().fileExists(path)) || | ||||
|                         (!defaultPath.empty() && | ||||
|                          ResourceManager::getInstance()->fileExists(defaultPath))) { | ||||
|                          ResourceManager::getInstance().fileExists(defaultPath))) { | ||||
|                         auto* logo = new ImageComponent(mWindow, false, false); | ||||
|                         logo->applyTheme(theme, "system", "logoPlaceholderImage", ThemeFlags::ALL); | ||||
|                         if (!logoElem->has("size")) | ||||
|  |  | |||
|  | @ -16,25 +16,7 @@ | |||
| #include "utils/StringUtil.h" | ||||
| #include "views/ViewController.h" | ||||
| 
 | ||||
| UIModeController* UIModeController::sInstance = nullptr; | ||||
| 
 | ||||
| UIModeController* UIModeController::getInstance() | ||||
| { | ||||
|     if (sInstance == nullptr) | ||||
|         sInstance = new UIModeController(); | ||||
| 
 | ||||
|     return sInstance; | ||||
| } | ||||
| 
 | ||||
| void UIModeController::deinit() | ||||
| { | ||||
|     if (sInstance) { | ||||
|         delete sInstance; | ||||
|         sInstance = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| UIModeController::UIModeController() | ||||
| UIModeController::UIModeController() noexcept | ||||
|     : mPassKeyCounter(0) | ||||
| { | ||||
|     mPassKeySequence = Settings::getInstance()->getString("UIMode_passkey"); | ||||
|  | @ -47,6 +29,12 @@ UIModeController::UIModeController() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| UIModeController* UIModeController::getInstance() | ||||
| { | ||||
|     static UIModeController instance; | ||||
|     return &instance; | ||||
| } | ||||
| 
 | ||||
| void UIModeController::monitorUIMode() | ||||
| { | ||||
|     std::string uimode = Settings::getInstance()->getString("UIMode"); | ||||
|  |  | |||
|  | @ -23,7 +23,6 @@ class UIModeController | |||
| { | ||||
| public: | ||||
|     static UIModeController* getInstance(); | ||||
|     static void deinit(); | ||||
| 
 | ||||
|     // Monitor input for UI mode change, returns true (consumes input) when a UI mode
 | ||||
|     // change is triggered.
 | ||||
|  | @ -42,15 +41,14 @@ public: | |||
|     void setCurrentUIMode(const std::string& mode) { mCurrentUIMode = mode; } | ||||
| 
 | ||||
| private: | ||||
|     UIModeController(); | ||||
|     UIModeController() noexcept; | ||||
| 
 | ||||
|     bool inputIsMatch(InputConfig* config, Input input); | ||||
|     bool isValidInput(InputConfig* config, Input input); | ||||
| 
 | ||||
|     // Return UI mode to 'full'.
 | ||||
|     void unlockUIMode(); | ||||
| 
 | ||||
|     static UIModeController* sInstance; | ||||
| 
 | ||||
|     // Default passkeyseq = "uuddlrlrba", as defined in the setting 'UIMode_passkey'.
 | ||||
|     std::string mPassKeySequence; | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,8 +33,6 @@ | |||
| #include "views/gamelist/IGameListView.h" | ||||
| #include "views/gamelist/VideoGameListView.h" | ||||
| 
 | ||||
| ViewController* ViewController::sInstance = nullptr; | ||||
| 
 | ||||
| #if defined(_MSC_VER) // MSVC compiler.
 | ||||
| const std::string ViewController::CONTROLLER_CHAR = Utils::String::wideStringToString(L"\uf11b"); | ||||
| const std::string ViewController::CROSSEDCIRCLE_CHAR = Utils::String::wideStringToString(L"\uf05e"); | ||||
|  | @ -59,18 +57,12 @@ const std::string ViewController::TICKMARK_CHAR = "\uf14a"; | |||
| 
 | ||||
| ViewController* ViewController::get() | ||||
| { | ||||
|     assert(sInstance); | ||||
|     return sInstance; | ||||
|     static ViewController instance; | ||||
|     return &instance; | ||||
| } | ||||
| 
 | ||||
| void ViewController::init(Window* window) | ||||
| { | ||||
|     assert(!sInstance); | ||||
|     sInstance = new ViewController(window); | ||||
| } | ||||
| 
 | ||||
| ViewController::ViewController(Window* window) | ||||
|     : GuiComponent(window) | ||||
| ViewController::ViewController() noexcept | ||||
|     : GuiComponent(Window::getInstance()) | ||||
|     , mNoGamesMessageBox(nullptr) | ||||
|     , mCurrentView(nullptr) | ||||
|     , mPreviousView(nullptr) | ||||
|  | @ -88,13 +80,6 @@ ViewController::ViewController(Window* window) | |||
|     mState.viewstyle = AUTOMATIC; | ||||
| } | ||||
| 
 | ||||
| ViewController::~ViewController() | ||||
| { | ||||
|     assert(sInstance == this); | ||||
|     sInstance = nullptr; | ||||
|     UIModeController::deinit(); | ||||
| } | ||||
| 
 | ||||
| void ViewController::invalidSystemsFileDialog() | ||||
| { | ||||
|     std::string errorMessage = "COULDN'T PARSE THE SYSTEMS CONFIGURATION FILE.\n" | ||||
|  |  | |||
|  | @ -29,11 +29,8 @@ class SystemView; | |||
| class ViewController : public GuiComponent | ||||
| { | ||||
| public: | ||||
|     static void init(Window* window); | ||||
|     static ViewController* get(); | ||||
| 
 | ||||
|     virtual ~ViewController(); | ||||
| 
 | ||||
|     // These functions are called from main().
 | ||||
|     void invalidSystemsFileDialog(); | ||||
|     void noGamesDialog(); | ||||
|  | @ -131,8 +128,7 @@ public: | |||
|     static const std::string TICKMARK_CHAR; | ||||
| 
 | ||||
| private: | ||||
|     ViewController(Window* window); | ||||
|     static ViewController* sInstance; | ||||
|     ViewController() noexcept; | ||||
| 
 | ||||
|     void launch(FileData* game); | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,8 +55,8 @@ void BasicGameListView::populateList(const std::vector<FileData*>& files, FileDa | |||
|     std::string editingCollection; | ||||
|     std::string inCollectionPrefix; | ||||
| 
 | ||||
|     if (CollectionSystemsManager::get()->isEditing()) { | ||||
|         editingCollection = CollectionSystemsManager::get()->getEditingCollection(); | ||||
|     if (CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|         editingCollection = CollectionSystemsManager::getInstance()->getEditingCollection(); | ||||
|         isEditing = true; | ||||
|     } | ||||
| 
 | ||||
|  | @ -78,7 +78,8 @@ void BasicGameListView::populateList(const std::vector<FileData*>& files, FileDa | |||
|             // Add a leading tick mark icon to the game name if it's part of the custom collection
 | ||||
|             // currently being edited.
 | ||||
|             if (isEditing && (*it)->getType() == GAME) { | ||||
|                 if (CollectionSystemsManager::get()->inCustomCollection(editingCollection, (*it))) { | ||||
|                 if (CollectionSystemsManager::getInstance()->inCustomCollection(editingCollection, | ||||
|                                                                                 (*it))) { | ||||
|                     if (Settings::getInstance()->getBool("SpecialCharsASCII")) | ||||
|                         inCollectionPrefix = "! "; | ||||
|                     else | ||||
|  | @ -323,7 +324,7 @@ std::vector<HelpPrompt> BasicGameListView::getHelpPrompts() | |||
|         prompts.push_back(HelpPrompt("thumbstickclick", "random")); | ||||
| 
 | ||||
|     if (mRoot->getSystem()->getThemeFolder() == "custom-collections" && | ||||
|         !CollectionSystemsManager::get()->isEditing() && mCursorStack.empty() && | ||||
|         !CollectionSystemsManager::getInstance()->isEditing() && mCursorStack.empty() && | ||||
|         ViewController::get()->getState().viewing == ViewController::GAME_LIST && | ||||
|         ViewController::get()->getState().viewstyle != ViewController::BASIC) { | ||||
|         prompts.push_back(HelpPrompt("y", "jump to game")); | ||||
|  | @ -334,14 +335,14 @@ std::vector<HelpPrompt> BasicGameListView::getHelpPrompts() | |||
|              !UIModeController::getInstance()->isUIModeKid() && | ||||
|              !UIModeController::getInstance()->isUIModeKiosk() && | ||||
|              (Settings::getInstance()->getBool("FavoritesAddButton") || | ||||
|               CollectionSystemsManager::get()->isEditing())) { | ||||
|         std::string prompt = CollectionSystemsManager::get()->getEditingCollection(); | ||||
|               CollectionSystemsManager::getInstance()->isEditing())) { | ||||
|         std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection(); | ||||
|         prompts.push_back(HelpPrompt("y", prompt)); | ||||
|     } | ||||
|     else if (mRoot->getSystem()->isGameSystem() && | ||||
|              mRoot->getSystem()->getThemeFolder() == "custom-collections" && | ||||
|              CollectionSystemsManager::get()->isEditing()) { | ||||
|         std::string prompt = CollectionSystemsManager::get()->getEditingCollection(); | ||||
|              CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|         std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection(); | ||||
|         prompts.push_back(HelpPrompt("y", prompt)); | ||||
|     } | ||||
|     return prompts; | ||||
|  |  | |||
|  | @ -338,8 +338,8 @@ void DetailedGameListView::updateInfoPanel() | |||
|         // the first of these so that we can display its game media.
 | ||||
|         if (file->getSystem()->isCustomCollection() && | ||||
|             file->getPath() == file->getSystem()->getName()) { | ||||
|             mRandomGame = | ||||
|                 CollectionSystemsManager::get()->updateCollectionFolderMetadata(file->getSystem()); | ||||
|             mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata( | ||||
|                 file->getSystem()); | ||||
|             if (mRandomGame) { | ||||
|                 mThumbnail.setImage(mRandomGame->getThumbnailPath()); | ||||
|                 mMarquee.setImage(mRandomGame->getMarqueePath(), false, true); | ||||
|  |  | |||
|  | @ -712,14 +712,14 @@ std::vector<HelpPrompt> GridGameListView::getHelpPrompts() | |||
|         !UIModeController::getInstance()->isUIModeKid() && | ||||
|         !UIModeController::getInstance()->isUIModeKiosk() && | ||||
|         (Settings::getInstance()->getBool("FavoritesAddButton") || | ||||
|          CollectionSystemsManager::get()->isEditing())) { | ||||
|         std::string prompt = CollectionSystemsManager::get()->getEditingCollection(); | ||||
|          CollectionSystemsManager::getInstance()->isEditing())) { | ||||
|         std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection(); | ||||
|         prompts.push_back(HelpPrompt("y", prompt)); | ||||
|     } | ||||
|     else if (mRoot->getSystem()->isGameSystem() && | ||||
|              mRoot->getSystem()->getThemeFolder() == "custom-collections" && | ||||
|              CollectionSystemsManager::get()->isEditing()) { | ||||
|         std::string prompt = CollectionSystemsManager::get()->getEditingCollection(); | ||||
|              CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|         std::string prompt = CollectionSystemsManager::getInstance()->getEditingCollection(); | ||||
|         prompts.push_back(HelpPrompt("y", prompt)); | ||||
|     } | ||||
|     return prompts; | ||||
|  |  | |||
|  | @ -237,7 +237,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input) | |||
|         } | ||||
|         else if (config->isMappedTo("y", input) && | ||||
|                  mRoot->getSystem()->getThemeFolder() == "custom-collections" && | ||||
|                  !CollectionSystemsManager::get()->isEditing() && mCursorStack.empty() && | ||||
|                  !CollectionSystemsManager::getInstance()->isEditing() && mCursorStack.empty() && | ||||
|                  ViewController::get()->getState().viewing == ViewController::GAME_LIST) { | ||||
|             // Jump to the randomly selected game.
 | ||||
|             if (mRandomGame) { | ||||
|  | @ -262,21 +262,21 @@ bool ISimpleGameListView::input(InputConfig* config, Input input) | |||
|         } | ||||
|         else if (config->isMappedTo("y", input) && | ||||
|                  !Settings::getInstance()->getBool("FavoritesAddButton") && | ||||
|                  !CollectionSystemsManager::get()->isEditing()) { | ||||
|                  !CollectionSystemsManager::getInstance()->isEditing()) { | ||||
|             return true; | ||||
|         } | ||||
|         else if (config->isMappedTo("y", input) && | ||||
|                  !UIModeController::getInstance()->isUIModeKid() && | ||||
|                  !UIModeController::getInstance()->isUIModeKiosk()) { | ||||
|             // Notify the user if attempting to add a custom collection to a custom collection.
 | ||||
|             if (CollectionSystemsManager::get()->isEditing() && | ||||
|             if (CollectionSystemsManager::getInstance()->isEditing() && | ||||
|                 mRoot->getSystem()->isGameSystem() && getCursor()->getType() != PLACEHOLDER && | ||||
|                 getCursor()->getParent()->getPath() == "collections") { | ||||
|                 NavigationSounds::getInstance().playThemeNavigationSound(FAVORITESOUND); | ||||
|                 mWindow->queueInfoPopup("CAN'T ADD CUSTOM COLLECTIONS TO CUSTOM COLLECTIONS", 4000); | ||||
|             } | ||||
|             // Notify the user if attempting to add a placeholder to a custom collection.
 | ||||
|             if (CollectionSystemsManager::get()->isEditing() && | ||||
|             if (CollectionSystemsManager::getInstance()->isEditing() && | ||||
|                 mRoot->getSystem()->isGameSystem() && getCursor()->getType() == PLACEHOLDER) { | ||||
|                 NavigationSounds::getInstance().playThemeNavigationSound(FAVORITESOUND); | ||||
|                 mWindow->queueInfoPopup("CAN'T ADD PLACEHOLDERS TO CUSTOM COLLECTIONS", 4000); | ||||
|  | @ -293,7 +293,7 @@ bool ISimpleGameListView::input(InputConfig* config, Input input) | |||
|                 bool favoritesSorting; | ||||
|                 bool removedLastFavorite = false; | ||||
|                 bool selectLastEntry = false; | ||||
|                 bool isEditing = CollectionSystemsManager::get()->isEditing(); | ||||
|                 bool isEditing = CollectionSystemsManager::getInstance()->isEditing(); | ||||
|                 bool foldersOnTop = Settings::getInstance()->getBool("FoldersOnTop"); | ||||
|                 // If the current list only contains folders, then treat it as if the folders
 | ||||
|                 // are not sorted on top, this way the logic should work exactly as for mixed
 | ||||
|  | @ -439,7 +439,8 @@ bool ISimpleGameListView::input(InputConfig* config, Input input) | |||
|                                             "AS GAMES TO CUSTOM COLLECTIONS", | ||||
|                                             4000); | ||||
|                 } | ||||
|                 else if (CollectionSystemsManager::get()->toggleGameInCollection(entryToUpdate)) { | ||||
|                 else if (CollectionSystemsManager::getInstance()->toggleGameInCollection( | ||||
|                              entryToUpdate)) { | ||||
|                     // As the toggling of the game destroyed this object, we need to get the view
 | ||||
|                     // from ViewController instead of using the reference that existed before the
 | ||||
|                     // destruction. Otherwise we get random crashes.
 | ||||
|  |  | |||
|  | @ -349,8 +349,8 @@ void VideoGameListView::updateInfoPanel() | |||
|         // the first of these so that we can display its game media.
 | ||||
|         if (file->getSystem()->isCustomCollection() && | ||||
|             file->getPath() == file->getSystem()->getName()) { | ||||
|             mRandomGame = | ||||
|                 CollectionSystemsManager::get()->updateCollectionFolderMetadata(file->getSystem()); | ||||
|             mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata( | ||||
|                 file->getSystem()); | ||||
|             if (mRandomGame) { | ||||
|                 mThumbnail.setImage(mRandomGame->getThumbnailPath()); | ||||
|                 mMarquee.setImage(mRandomGame->getMarqueePath(), false, true); | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| 
 | ||||
| #include <SDL2/SDL.h> | ||||
| 
 | ||||
| AudioManager::AudioManager() | ||||
| AudioManager::AudioManager() noexcept | ||||
| { | ||||
|     // Init on construction.
 | ||||
|     init(); | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ public: | |||
|     inline static SDL_AudioSpec sAudioFormat; | ||||
| 
 | ||||
| private: | ||||
|     AudioManager(); | ||||
|     AudioManager() noexcept; | ||||
| 
 | ||||
|     static void mixAudio(void* unused, Uint8* stream, int len); | ||||
|     static void mixAudio2(void* unused, Uint8* stream, int len); | ||||
|  |  | |||
|  | @ -30,8 +30,6 @@ extern "C" { | |||
| extern int SDL_USER_CECBUTTONDOWN; | ||||
| extern int SDL_USER_CECBUTTONUP; | ||||
| 
 | ||||
| CECInput* CECInput::sInstance = nullptr; | ||||
| 
 | ||||
| #if defined(HAVE_LIBCEC) | ||||
| static void onAlert(void* /*cbParam*/, | ||||
|                     const CEC::libcec_alert type, | ||||
|  | @ -80,20 +78,6 @@ static void vchi_tv_and_cec_deinit() | |||
| #endif // _RPI_
 | ||||
| #endif // HAVE_LIBCEC
 | ||||
| 
 | ||||
| void CECInput::init() | ||||
| { | ||||
|     if (!sInstance) | ||||
|         sInstance = new CECInput(); | ||||
| } | ||||
| 
 | ||||
| void CECInput::deinit() | ||||
| { | ||||
|     if (sInstance) { | ||||
|         delete sInstance; | ||||
|         sInstance = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CECInput::CECInput() | ||||
|     : mlibCEC(nullptr) | ||||
| { | ||||
|  |  | |||
|  | @ -19,18 +19,14 @@ namespace CEC | |||
| class CECInput | ||||
| { | ||||
| public: | ||||
|     static void init(); | ||||
|     static void deinit(); | ||||
|     CECInput(); | ||||
|     ~CECInput(); | ||||
| 
 | ||||
|     static std::string getAlertTypeString(const unsigned int _type); | ||||
|     static std::string getOpCodeString(const unsigned int _opCode); | ||||
|     static std::string getKeyCodeString(const unsigned int _keyCode); | ||||
| 
 | ||||
| private: | ||||
|     CECInput(); | ||||
|     ~CECInput(); | ||||
| 
 | ||||
|     static CECInput* sInstance; | ||||
| 
 | ||||
|     CEC::ICECAdapter* mlibCEC; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,7 +10,6 @@ | |||
| 
 | ||||
| #include "InputManager.h" | ||||
| 
 | ||||
| #include "CECInput.h" | ||||
| #include "Log.h" | ||||
| #include "Platform.h" | ||||
| #include "Scripting.h" | ||||
|  | @ -32,9 +31,7 @@ int SDL_USER_CECBUTTONUP = -1; | |||
| static bool sAltDown = false; | ||||
| static bool sLguiDown = false; | ||||
| 
 | ||||
| InputManager* InputManager::sInstance = nullptr; | ||||
| 
 | ||||
| InputManager::InputManager() | ||||
| InputManager::InputManager() noexcept | ||||
|     : mKeyboardInputConfig(nullptr) | ||||
| { | ||||
| } | ||||
|  | @ -45,12 +42,10 @@ InputManager::~InputManager() | |||
|     deinit(); | ||||
| } | ||||
| 
 | ||||
| InputManager* InputManager::getInstance() | ||||
| InputManager& InputManager::getInstance() | ||||
| { | ||||
|     if (!sInstance) | ||||
|         sInstance = new InputManager(); | ||||
| 
 | ||||
|     return sInstance; | ||||
|     static InputManager instance; | ||||
|     return instance; | ||||
| } | ||||
| 
 | ||||
| void InputManager::init() | ||||
|  | @ -94,7 +89,7 @@ void InputManager::init() | |||
|         Utils::FileSystem::getHomePath() + "/.emulationstation/" + "es_controller_mappings.cfg"; | ||||
| 
 | ||||
|     if (!Utils::FileSystem::exists(mappingsFile)) | ||||
|         mappingsFile = ResourceManager::getInstance()->getResourcePath( | ||||
|         mappingsFile = ResourceManager::getInstance().getResourcePath( | ||||
|             ":/controllers/es_controller_mappings.cfg"); | ||||
| 
 | ||||
|     int controllerMappings = SDL_GameControllerAddMappingsFromFile(mappingsFile.c_str()); | ||||
|  | @ -116,7 +111,6 @@ void InputManager::init() | |||
| 
 | ||||
|     SDL_USER_CECBUTTONDOWN = SDL_RegisterEvents(2); | ||||
|     SDL_USER_CECBUTTONUP = SDL_USER_CECBUTTONDOWN + 1; | ||||
|     CECInput::init(); | ||||
|     mCECInputConfig = std::make_unique<InputConfig>(DEVICE_CEC, "CEC", CEC_GUID_STRING); | ||||
|     loadInputConfig(mCECInputConfig.get()); | ||||
| } | ||||
|  | @ -138,15 +132,8 @@ void InputManager::deinit() | |||
|     mKeyboardInputConfig.reset(); | ||||
|     mCECInputConfig.reset(); | ||||
| 
 | ||||
|     CECInput::deinit(); | ||||
| 
 | ||||
|     SDL_GameControllerEventState(SDL_DISABLE); | ||||
|     SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); | ||||
| 
 | ||||
|     if (sInstance) { | ||||
|         delete sInstance; | ||||
|         sInstance = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void InputManager::writeDeviceConfig(InputConfig* config) | ||||
|  |  | |||
|  | @ -11,6 +11,8 @@ | |||
| #ifndef ES_CORE_INPUT_MANAGER_H | ||||
| #define ES_CORE_INPUT_MANAGER_H | ||||
| 
 | ||||
| #include "CECInput.h" | ||||
| 
 | ||||
| #include <SDL2/SDL.h> | ||||
| #include <SDL2/SDL_joystick.h> | ||||
| 
 | ||||
|  | @ -25,9 +27,7 @@ union SDL_Event; | |||
| class InputManager | ||||
| { | ||||
| public: | ||||
|     InputManager(); | ||||
|     virtual ~InputManager(); | ||||
|     static InputManager* getInstance(); | ||||
|     static InputManager& getInstance(); | ||||
| 
 | ||||
|     void init(); | ||||
|     void deinit(); | ||||
|  | @ -50,6 +50,9 @@ public: | |||
|     int getNumJoysticks() { return static_cast<int>(mJoysticks.size()); } | ||||
| 
 | ||||
| private: | ||||
|     InputManager() noexcept; | ||||
|     virtual ~InputManager(); | ||||
| 
 | ||||
|     bool initialized() const { return mKeyboardInputConfig != nullptr; } | ||||
| 
 | ||||
|     bool loadInputConfig(InputConfig* config); | ||||
|  | @ -59,7 +62,8 @@ private: | |||
|     void addControllerByDeviceIndex(Window* window, int deviceIndex); | ||||
|     void removeControllerByJoystickID(Window* window, SDL_JoystickID joyID); | ||||
| 
 | ||||
|     static InputManager* sInstance; | ||||
|     CECInput mCECInput; | ||||
| 
 | ||||
|     static const int DEADZONE_TRIGGERS = 18000; | ||||
|     static const int DEADZONE_THUMBSTICKS = 23000; | ||||
|     bool mConfigFileExists; | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ MameNames& MameNames::getInstance() | |||
| 
 | ||||
| MameNames::MameNames() | ||||
| { | ||||
|     std::string xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamenames.xml"); | ||||
|     std::string xmlpath = ResourceManager::getInstance().getResourcePath(":/MAME/mamenames.xml"); | ||||
| 
 | ||||
|     if (!Utils::FileSystem::exists(xmlpath)) | ||||
|         return; | ||||
|  | @ -54,7 +54,7 @@ MameNames::MameNames() | |||
|     } | ||||
| 
 | ||||
|     // Read BIOS file.
 | ||||
|     xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamebioses.xml"); | ||||
|     xmlpath = ResourceManager::getInstance().getResourcePath(":/MAME/mamebioses.xml"); | ||||
| 
 | ||||
|     if (!Utils::FileSystem::exists(xmlpath)) | ||||
|         return; | ||||
|  | @ -80,7 +80,7 @@ MameNames::MameNames() | |||
|     } | ||||
| 
 | ||||
|     // Read device file.
 | ||||
|     xmlpath = ResourceManager::getInstance()->getResourcePath(":/MAME/mamedevices.xml"); | ||||
|     xmlpath = ResourceManager::getInstance().getResourcePath(":/MAME/mamedevices.xml"); | ||||
| 
 | ||||
|     if (!Utils::FileSystem::exists(xmlpath)) | ||||
|         return; | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ std::shared_ptr<Sound> Sound::getFromTheme(ThemeData* const theme, | |||
|     if (theme == nullptr) { | ||||
|         LOG(LogDebug) << "Sound::getFromTheme(): Using fallback sound file for \"" << element | ||||
|                       << "\""; | ||||
|         return get(ResourceManager::getInstance()->getResourcePath(":/sounds/" + element + ".wav")); | ||||
|         return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + element + ".wav")); | ||||
|     } | ||||
| 
 | ||||
|     LOG(LogDebug) << "Sound::getFromTheme(): Looking for tag <sound name=\"" << element << "\">"; | ||||
|  | @ -44,7 +44,7 @@ std::shared_ptr<Sound> Sound::getFromTheme(ThemeData* const theme, | |||
|     const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound"); | ||||
|     if (!elem || !elem->has("path")) { | ||||
|         LOG(LogDebug) << "Sound::getFromTheme(): Tag not found, using fallback sound file"; | ||||
|         return get(ResourceManager::getInstance()->getResourcePath(":/sounds/" + element + ".wav")); | ||||
|         return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + element + ".wav")); | ||||
|     } | ||||
| 
 | ||||
|     LOG(LogDebug) << "Sound::getFromTheme(): Tag found, ready to load theme sound file"; | ||||
|  |  | |||
|  | @ -77,6 +77,7 @@ public: | |||
|     bool isPlayingThemeNavigationSound(NavigationSoundsID soundID); | ||||
| 
 | ||||
| private: | ||||
|     NavigationSounds() noexcept {}; | ||||
|     std::vector<std::shared_ptr<Sound>> mNavigationSounds; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -321,7 +321,7 @@ void ThemeData::parseIncludes(const pugi::xml_node& root) | |||
|     for (pugi::xml_node node = root.child("include"); node; node = node.next_sibling("include")) { | ||||
|         std::string relPath = resolvePlaceholders(node.text().as_string()); | ||||
|         std::string path = Utils::FileSystem::resolveRelativePath(relPath, mPaths.back(), true); | ||||
|         if (!ResourceManager::getInstance()->fileExists(path)) | ||||
|         if (!ResourceManager::getInstance().fileExists(path)) | ||||
|             throw error << " -> \"" << relPath << "\" not found (resolved to \"" << path << "\")"; | ||||
|         error << " -> \"" << relPath << "\""; | ||||
| 
 | ||||
|  | @ -512,7 +512,7 @@ void ThemeData::parseElement(const pugi::xml_node& root, | |||
|             } | ||||
|             case PATH: { | ||||
|                 std::string path = Utils::FileSystem::resolveRelativePath(str, mPaths.back(), true); | ||||
|                 if (!ResourceManager::getInstance()->fileExists(path)) { | ||||
|                 if (!ResourceManager::getInstance().fileExists(path)) { | ||||
|                     std::stringstream ss; | ||||
|                     // "From theme yadda yadda, included file yadda yadda.
 | ||||
|                     LOG(LogWarning) << error.msg << ":"; | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ | |||
| #define CLOCK_BACKGROUND_CREATION false | ||||
| #endif | ||||
| 
 | ||||
| Window::Window() | ||||
| Window::Window() noexcept | ||||
|     : mScreensaver(nullptr) | ||||
|     , mMediaViewer(nullptr) | ||||
|     , mLaunchScreen(nullptr) | ||||
|  | @ -48,9 +48,6 @@ Window::Window() | |||
|     , mTopScale(0.5) | ||||
|     , mChangedThemeSet(false) | ||||
| { | ||||
|     mHelp = new HelpComponent(this); | ||||
|     mBackgroundOverlay = new ImageComponent(this); | ||||
|     mBackgroundOverlayOpacity = 0; | ||||
| } | ||||
| 
 | ||||
| Window::~Window() | ||||
|  | @ -67,6 +64,12 @@ Window::~Window() | |||
|     delete mHelp; | ||||
| } | ||||
| 
 | ||||
| Window* Window::getInstance() | ||||
| { | ||||
|     static Window instance; | ||||
|     return &instance; | ||||
| } | ||||
| 
 | ||||
| void Window::pushGui(GuiComponent* gui) | ||||
| { | ||||
|     if (mGuiStack.size() > 0) { | ||||
|  | @ -109,9 +112,13 @@ bool Window::init() | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     InputManager::getInstance()->init(); | ||||
|     InputManager::getInstance().init(); | ||||
| 
 | ||||
|     ResourceManager::getInstance()->reloadAll(); | ||||
|     ResourceManager::getInstance().reloadAll(); | ||||
| 
 | ||||
|     mHelp = new HelpComponent(this); | ||||
|     mBackgroundOverlay = new ImageComponent(this); | ||||
|     mBackgroundOverlayOpacity = 0; | ||||
| 
 | ||||
|     // Keep a reference to the default fonts, so they don't keep getting destroyed/recreated.
 | ||||
|     if (mDefaultFonts.empty()) { | ||||
|  | @ -147,8 +154,8 @@ void Window::deinit() | |||
|     mPostprocessedBackground.reset(); | ||||
| #endif | ||||
| 
 | ||||
|     InputManager::getInstance()->deinit(); | ||||
|     ResourceManager::getInstance()->unloadAll(); | ||||
|     InputManager::getInstance().deinit(); | ||||
|     ResourceManager::getInstance().unloadAll(); | ||||
|     Renderer::deinit(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -75,8 +75,7 @@ public: | |||
|         virtual void render(const glm::mat4& parentTrans) = 0; | ||||
|     }; | ||||
| 
 | ||||
|     Window(); | ||||
|     ~Window(); | ||||
|     static Window* getInstance(); | ||||
| 
 | ||||
|     void pushGui(GuiComponent* gui); | ||||
|     void removeGui(GuiComponent* gui); | ||||
|  | @ -147,6 +146,9 @@ public: | |||
|     bool getChangedThemeSet() { return mChangedThemeSet; } | ||||
| 
 | ||||
| private: | ||||
|     Window() noexcept; | ||||
|     ~Window(); | ||||
| 
 | ||||
|     void onSleep() { Scripting::fireEvent("sleep"); } | ||||
|     void onWake() { Scripting::fireEvent("wake"); } | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ void AnimatedImageComponent::load(const AnimationDef* def) | |||
| 
 | ||||
|     for (size_t i = 0; i < def->frameCount; ++i) { | ||||
|         if (def->frames[i].path != "" && | ||||
|             !ResourceManager::getInstance()->fileExists(def->frames[i].path)) { | ||||
|             !ResourceManager::getInstance().fileExists(def->frames[i].path)) { | ||||
|             LOG(LogError) << "Missing animation frame " << i << " (\"" << def->frames[i].path | ||||
|                           << "\")"; | ||||
|             continue; | ||||
|  |  | |||
|  | @ -269,7 +269,7 @@ std::shared_ptr<TextureResource> HelpComponent::getIconTexture(const char* name) | |||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     if (!ResourceManager::getInstance()->fileExists(pathLookup->second)) { | ||||
|     if (!ResourceManager::getInstance().fileExists(pathLookup->second)) { | ||||
|         LOG(LogError) << "Couldn't load help icon \"" << name << "\" as the file \"" | ||||
|                       << pathLookup->second << "\" is missing"; | ||||
|         return nullptr; | ||||
|  |  | |||
|  | @ -140,8 +140,8 @@ void ImageComponent::setImage(const std::string& path, bool tile, bool linearMag | |||
|         mDynamic = false; | ||||
|     } | ||||
| 
 | ||||
|     if (path.empty() || !ResourceManager::getInstance()->fileExists(path)) { | ||||
|         if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath)) | ||||
|     if (path.empty() || !ResourceManager::getInstance().fileExists(path)) { | ||||
|         if (mDefaultPath.empty() || !ResourceManager::getInstance().fileExists(mDefaultPath)) | ||||
|             mTexture.reset(); | ||||
|         else | ||||
|             mTexture = | ||||
|  |  | |||
|  | @ -327,7 +327,7 @@ void ImageGridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, | |||
|         if (elem->has("gameImage")) { | ||||
|             std::string path = elem->get<std::string>("gameImage"); | ||||
| 
 | ||||
|             if (!ResourceManager::getInstance()->fileExists(path)) { | ||||
|             if (!ResourceManager::getInstance().fileExists(path)) { | ||||
|                 LOG(LogWarning) << "Could not replace default game image, check path: " << path; | ||||
|             } | ||||
|             else { | ||||
|  | @ -346,7 +346,7 @@ void ImageGridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, | |||
|         if (elem->has("folderImage")) { | ||||
|             std::string path = elem->get<std::string>("folderImage"); | ||||
| 
 | ||||
|             if (!ResourceManager::getInstance()->fileExists(path)) { | ||||
|             if (!ResourceManager::getInstance().fileExists(path)) { | ||||
|                 LOG(LogWarning) << "Could not replace default folder image, check path: " << path; | ||||
|             } | ||||
|             else { | ||||
|  | @ -658,7 +658,7 @@ void ImageGridComponent<T>::updateTileAtPos(int tilePos, | |||
| 
 | ||||
|         std::string imagePath = mEntries.at(imgPos).data.texturePath; | ||||
| 
 | ||||
|         if (ResourceManager::getInstance()->fileExists(imagePath)) | ||||
|         if (ResourceManager::getInstance().fileExists(imagePath)) | ||||
|             tile->setImage(imagePath); | ||||
|         else if (mEntries.at(imgPos).object->getType() == 2) | ||||
|             tile->setImage(mDefaultFolderTexture); | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ bool VideoComponent::setVideo(std::string path) | |||
|     mVideoPath = fullPath; | ||||
| 
 | ||||
|     // If the file exists then set the new video.
 | ||||
|     if (!fullPath.empty() && ResourceManager::getInstance()->fileExists(fullPath)) { | ||||
|     if (!fullPath.empty() && ResourceManager::getInstance().fileExists(fullPath)) { | ||||
|         // Return true to show that we are going to attempt to play a video.
 | ||||
|         return true; | ||||
|     } | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ GuiDetectDevice::GuiDetectDevice(Window* window, | |||
| 
 | ||||
|     // Device info.
 | ||||
|     std::stringstream deviceInfo; | ||||
|     int numDevices = InputManager::getInstance()->getNumJoysticks(); | ||||
|     int numDevices = InputManager::getInstance().getNumJoysticks(); | ||||
| 
 | ||||
|     if (numDevices > 0) | ||||
|         deviceInfo << numDevices << " GAMEPAD" << (numDevices > 1 ? "S" : "") << " DETECTED"; | ||||
|  | @ -148,7 +148,7 @@ void GuiDetectDevice::update(int deltaTime) | |||
|         // command line.
 | ||||
|         if (!mForcedConfig && mFirstRun && | ||||
|             Utils::FileSystem::exists(InputManager::getConfigPath()) && | ||||
|             InputManager::getInstance()->getNumConfiguredDevices() > 0) { | ||||
|             InputManager::getInstance().getNumConfiguredDevices() > 0) { | ||||
|             if (mDoneCallback) | ||||
|                 mDoneCallback(); | ||||
|             delete this; // Delete GUI element.
 | ||||
|  |  | |||
|  | @ -174,7 +174,7 @@ GuiInputConfig::GuiInputConfig(Window* window, | |||
|     // GUI buttons.
 | ||||
|     std::vector<std::shared_ptr<ButtonComponent>> buttons; | ||||
|     std::function<void()> okFunction = [this, okCallback] { | ||||
|         InputManager::getInstance()->writeDeviceConfig(mTargetConfig); // Save.
 | ||||
|         InputManager::getInstance().writeDeviceConfig(mTargetConfig); // Save.
 | ||||
|         if (okCallback) | ||||
|             okCallback(); | ||||
|         delete this; | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ namespace Renderer | |||
|         size_t width = 0; | ||||
|         size_t height = 0; | ||||
|         ResourceData resData = | ||||
|             ResourceManager::getInstance()->getFileData(":/graphics/window_icon_256.png"); | ||||
|             ResourceManager::getInstance().getFileData(":/graphics/window_icon_256.png"); | ||||
|         std::vector<unsigned char> rawData = | ||||
|             ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height); | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ namespace Renderer | |||
|         std::string shaderCode; | ||||
| 
 | ||||
|         // This will load the entire GLSL source code into the string variable.
 | ||||
|         const ResourceData& shaderData = ResourceManager::getInstance()->getFileData(path); | ||||
|         const ResourceData& shaderData = ResourceManager::getInstance().getFileData(path); | ||||
|         shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length); | ||||
| 
 | ||||
|         // Define the GLSL version (version 120 = OpenGL 2.1).
 | ||||
|  |  | |||
|  | @ -128,7 +128,7 @@ std::shared_ptr<Font> Font::get(int size, const std::string& path) | |||
| 
 | ||||
|     std::shared_ptr<Font> font = std::shared_ptr<Font>(new Font(def.second, def.first)); | ||||
|     sFontMap[def] = std::weak_ptr<Font>(font); | ||||
|     ResourceManager::getInstance()->addReloadable(font); | ||||
|     ResourceManager::getInstance().addReloadable(font); | ||||
|     return font; | ||||
| } | ||||
| 
 | ||||
|  | @ -243,25 +243,25 @@ std::vector<std::string> getFallbackFontPaths() | |||
| 
 | ||||
|     // Standard fonts, let's include them here for exception handling purposes even though that's
 | ||||
|     // not really the correct location. (The application will crash if they are missing.)
 | ||||
|     ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-Regular.ttf"); | ||||
|     ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-SemiBold.ttf"); | ||||
|     ResourceManager::getInstance()->getResourcePath(":/fonts/Akrobat-Bold.ttf"); | ||||
|     ResourceManager::getInstance().getResourcePath(":/fonts/Akrobat-Regular.ttf"); | ||||
|     ResourceManager::getInstance().getResourcePath(":/fonts/Akrobat-SemiBold.ttf"); | ||||
|     ResourceManager::getInstance().getResourcePath(":/fonts/Akrobat-Bold.ttf"); | ||||
| 
 | ||||
|     // Vera sans Unicode.
 | ||||
|     fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/DejaVuSans.ttf")); | ||||
|     fontPaths.push_back(ResourceManager::getInstance().getResourcePath(":/fonts/DejaVuSans.ttf")); | ||||
|     // GNU FreeFont monospaced.
 | ||||
|     fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/FreeMono.ttf")); | ||||
|     fontPaths.push_back(ResourceManager::getInstance().getResourcePath(":/fonts/FreeMono.ttf")); | ||||
|     // Various languages, such as Japanese and Chinese.
 | ||||
|     fontPaths.push_back( | ||||
|         ResourceManager::getInstance()->getResourcePath(":/fonts/DroidSansFallbackFull.ttf")); | ||||
|         ResourceManager::getInstance().getResourcePath(":/fonts/DroidSansFallbackFull.ttf")); | ||||
|     // Korean.
 | ||||
|     fontPaths.push_back( | ||||
|         ResourceManager::getInstance()->getResourcePath(":/fonts/NanumMyeongjo.ttf")); | ||||
|         ResourceManager::getInstance().getResourcePath(":/fonts/NanumMyeongjo.ttf")); | ||||
|     // Font Awesome icon glyphs, used for various special symbols like stars, folders etc.
 | ||||
|     fontPaths.push_back( | ||||
|         ResourceManager::getInstance()->getResourcePath(":/fonts/fontawesome-webfont.ttf")); | ||||
|         ResourceManager::getInstance().getResourcePath(":/fonts/fontawesome-webfont.ttf")); | ||||
|     // This is only needed for some really rare special characters.
 | ||||
|     fontPaths.push_back(ResourceManager::getInstance()->getResourcePath(":/fonts/Ubuntu-C.ttf")); | ||||
|     fontPaths.push_back(ResourceManager::getInstance().getResourcePath(":/fonts/Ubuntu-C.ttf")); | ||||
| 
 | ||||
|     fontPaths.shrink_to_fit(); | ||||
|     return fontPaths; | ||||
|  | @ -281,7 +281,7 @@ FT_Face Font::getFaceForChar(unsigned int id) | |||
|             // i == 0 -> mPath
 | ||||
|             // Otherwise, take from fallbackFonts.
 | ||||
|             const std::string& path = (i == 0 ? mPath : fallbackFonts.at(i - 1)); | ||||
|             ResourceData data = ResourceManager::getInstance()->getFileData(path); | ||||
|             ResourceData data = ResourceManager::getInstance().getFileData(path); | ||||
|             mFaceCache[i] = std::unique_ptr<FontFace>(new FontFace(std::move(data), mSize)); | ||||
|             fit = mFaceCache.find(i); | ||||
|         } | ||||
|  |  | |||
|  | @ -90,8 +90,8 @@ public: | |||
|     float getHeight(float lineSpacing = 1.5f) const; | ||||
|     float getLetterHeight(); | ||||
| 
 | ||||
|     void reload(std::shared_ptr<ResourceManager>& rm) override { rebuildTextures(); } | ||||
|     void unload(std::shared_ptr<ResourceManager>& rm) override { unloadTextures(); } | ||||
|     void reload(ResourceManager& rm) override { rebuildTextures(); } | ||||
|     void unload(ResourceManager& rm) override { unloadTextures(); } | ||||
| 
 | ||||
|     int getSize() const { return mSize; } | ||||
|     const std::string& getPath() const { return mPath; } | ||||
|  |  | |||
|  | @ -19,14 +19,10 @@ | |||
| 
 | ||||
| auto array_deleter = [](unsigned char* p) { delete[] p; }; | ||||
| 
 | ||||
| std::shared_ptr<ResourceManager> ResourceManager::sInstance = nullptr; | ||||
| 
 | ||||
| std::shared_ptr<ResourceManager>& ResourceManager::getInstance() | ||||
| ResourceManager& ResourceManager::getInstance() | ||||
| { | ||||
|     if (!sInstance) | ||||
|         sInstance = std::shared_ptr<ResourceManager>(new ResourceManager()); | ||||
| 
 | ||||
|     return sInstance; | ||||
|     static ResourceManager instance; | ||||
|     return instance; | ||||
| } | ||||
| 
 | ||||
| std::string ResourceManager::getResourcePath(const std::string& path, bool terminateOnFailure) const | ||||
|  | @ -145,7 +141,7 @@ void ResourceManager::unloadAll() | |||
|     auto iter = mReloadables.cbegin(); | ||||
|     while (iter != mReloadables.cend()) { | ||||
|         if (!iter->expired()) { | ||||
|             iter->lock()->unload(sInstance); | ||||
|             iter->lock()->unload(getInstance()); | ||||
|             ++iter; | ||||
|         } | ||||
|         else { | ||||
|  | @ -159,7 +155,7 @@ void ResourceManager::reloadAll() | |||
|     auto iter = mReloadables.cbegin(); | ||||
|     while (iter != mReloadables.cend()) { | ||||
|         if (!iter->expired()) { | ||||
|             iter->lock()->reload(sInstance); | ||||
|             iter->lock()->reload(getInstance()); | ||||
|             ++iter; | ||||
|         } | ||||
|         else { | ||||
|  |  | |||
|  | @ -28,14 +28,14 @@ class ResourceManager; | |||
| class IReloadable | ||||
| { | ||||
| public: | ||||
|     virtual void unload(std::shared_ptr<ResourceManager>& rm) = 0; | ||||
|     virtual void reload(std::shared_ptr<ResourceManager>& rm) = 0; | ||||
|     virtual void unload(ResourceManager& rm) = 0; | ||||
|     virtual void reload(ResourceManager& rm) = 0; | ||||
| }; | ||||
| 
 | ||||
| class ResourceManager | ||||
| { | ||||
| public: | ||||
|     static std::shared_ptr<ResourceManager>& getInstance(); | ||||
|     static ResourceManager& getInstance(); | ||||
| 
 | ||||
|     void addReloadable(std::weak_ptr<IReloadable> reloadable); | ||||
| 
 | ||||
|  | @ -47,9 +47,8 @@ public: | |||
|     bool fileExists(const std::string& path) const; | ||||
| 
 | ||||
| private: | ||||
|     ResourceManager() {} | ||||
|     ResourceManager() noexcept {} | ||||
| 
 | ||||
|     static std::shared_ptr<ResourceManager> sInstance; | ||||
|     std::list<std::weak_ptr<IReloadable>> mReloadables; | ||||
| 
 | ||||
|     ResourceData loadFile(const std::string& path) const; | ||||
|  |  | |||
|  | @ -179,8 +179,7 @@ bool TextureData::load() | |||
| 
 | ||||
|     // Need to load. See if there is a file.
 | ||||
|     if (!mPath.empty()) { | ||||
|         std::shared_ptr<ResourceManager>& rm = ResourceManager::getInstance(); | ||||
|         const ResourceData& data = rm->getFileData(mPath); | ||||
|         const ResourceData& data = ResourceManager::getInstance().getFileData(mPath); | ||||
|         // Is it an SVG?
 | ||||
|         if (Utils::String::toLower(mPath.substr(mPath.size() - 4, std::string::npos)) == ".svg") { | ||||
|             mScalable = true; | ||||
|  |  | |||
|  | @ -148,14 +148,12 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path, | |||
|                                                       bool linearMagnify, | ||||
|                                                       bool forceRasterization) | ||||
| { | ||||
|     std::shared_ptr<ResourceManager>& rm = ResourceManager::getInstance(); | ||||
| 
 | ||||
|     const std::string canonicalPath = Utils::FileSystem::getCanonicalPath(path); | ||||
|     if (canonicalPath.empty()) { | ||||
|         std::shared_ptr<TextureResource> tex( | ||||
|             new TextureResource("", tile, false, linearMagnify, forceRasterization)); | ||||
|         // Make sure we get properly deinitialized even though we do nothing on reinitialization.
 | ||||
|         rm->addReloadable(tex); | ||||
|         ResourceManager::getInstance().addReloadable(tex); | ||||
|         return tex; | ||||
|     } | ||||
| 
 | ||||
|  | @ -182,7 +180,7 @@ std::shared_ptr<TextureResource> TextureResource::get(const std::string& path, | |||
|     } | ||||
| 
 | ||||
|     // Add it to the reloadable list.
 | ||||
|     rm->addReloadable(tex); | ||||
|     ResourceManager::getInstance().addReloadable(tex); | ||||
| 
 | ||||
|     // Force load it if necessary. Note that it may get dumped from VRAM if we run low.
 | ||||
|     if (forceLoad) { | ||||
|  | @ -241,7 +239,7 @@ size_t TextureResource::getTotalTextureSize() | |||
|     return total; | ||||
| } | ||||
| 
 | ||||
| void TextureResource::unload(std::shared_ptr<ResourceManager>& /*rm*/) | ||||
| void TextureResource::unload(ResourceManager& /*rm*/) | ||||
| { | ||||
|     // Release the texture's resources.
 | ||||
|     std::shared_ptr<TextureData> data; | ||||
|  | @ -254,7 +252,7 @@ void TextureResource::unload(std::shared_ptr<ResourceManager>& /*rm*/) | |||
|     data->releaseRAM(); | ||||
| } | ||||
| 
 | ||||
| void TextureResource::reload(std::shared_ptr<ResourceManager>& /*rm*/) | ||||
| void TextureResource::reload(ResourceManager& /*rm*/) | ||||
| { | ||||
|     // For dynamically loaded textures the texture manager will load them on demand.
 | ||||
|     // For manually loaded textures we have to reload them here.
 | ||||
|  |  | |||
|  | @ -68,8 +68,8 @@ protected: | |||
|                     bool dynamic, | ||||
|                     bool linearMagnify, | ||||
|                     bool forceRasterization); | ||||
|     virtual void unload(std::shared_ptr<ResourceManager>& rm); | ||||
|     virtual void reload(std::shared_ptr<ResourceManager>& rm); | ||||
|     virtual void unload(ResourceManager& rm); | ||||
|     virtual void reload(ResourceManager& rm); | ||||
| 
 | ||||
| private: | ||||
|     // mTextureData is used for textures that are not loaded from a file - these ones
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Leon Styhre
						Leon Styhre