1 /*
2 * Copyright (C) 2006-2019 Christopho, Solarus - http://www.solarus-games.org
3 *
4 * Solarus is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Solarus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "solarus/core/CurrentQuest.h"
18 #include "solarus/core/ResourceProvider.h"
19 #include "solarus/core/QuestDatabase.h"
20
21 namespace Solarus {
22
23 /**
24 * \brief Creates a resource provider.
25 */
ResourceProvider()26 ResourceProvider::ResourceProvider() {
27 }
28
29 /**
30 * \brief Preloads resources in background in a separate thread.
31 */
start_preloading_resources()32 void ResourceProvider::start_preloading_resources() {
33
34 // Put all tilesets in the cache, without loading them yet.
35 const QuestDatabase& database = CurrentQuest::get_database();
36 const QuestDatabase::ResourceMap& tileset_ids = database.get_resource_elements(ResourceType::TILESET);
37 std::vector<std::shared_ptr<Tileset>> tilesets_to_preload;
38 for (const auto& pair : tileset_ids) {
39 const std::string& tileset_id = pair.first;
40 std::shared_ptr<Tileset> tileset = std::make_shared<Tileset>(tileset_id);
41 tileset_cache.emplace(tileset_id, tileset);
42 tilesets_to_preload.emplace_back(tileset);
43 }
44
45 // Start loading them in a separate thread.
46 preloader_thread = std::thread([this, tilesets_to_preload]() {
47
48 for (const std::shared_ptr<Tileset>& tileset : tilesets_to_preload) {
49 if (tileset_cache.empty()) {
50 // clear() was probably called in the meantime.
51 // No reason to continue.
52 return;
53 }
54 tileset->load();
55 std::this_thread::yield();
56 }
57 });
58 }
59
60 /**
61 * \brief Clears all stored resources.
62 */
clear()63 void ResourceProvider::clear() {
64
65 tileset_cache.clear();
66 preloader_thread.join();
67 }
68
69 /**
70 * \brief Provides the tileset with the given id.
71 * \param tileset_id A tileset id.
72 * \return The corresponding tileset.
73 */
get_tileset(const std::string & tileset_id)74 Tileset& ResourceProvider::get_tileset(const std::string& tileset_id) {
75
76 std::shared_ptr<Tileset> tileset;
77 auto it = tileset_cache.find(tileset_id);
78 if (it->second != nullptr) {
79 tileset = it->second;
80 }
81 else {
82 tileset = std::make_shared<Tileset>(tileset_id);
83 tileset_cache.emplace(tileset_id, tileset);
84 }
85
86 tileset->load();
87
88 return *tileset;
89 }
90
91 /**
92 * \brief Returns all tilesets currently in cache.
93 * \return The loaded tilesets.
94 */
get_loaded_tilesets()95 const std::map<std::string, std::shared_ptr<Tileset>>& ResourceProvider::get_loaded_tilesets() {
96 return tileset_cache;
97 }
98
99 /**
100 * \brief Notifies the resource provider that cached data (if any) is no longer valid.
101 *
102 * This function must be called when a resource element has changed on disk.
103 *
104 * \param resource_type Type of resource that has changed.
105 * \param element_id Resource element that has changed.
106 */
invalidate_resource_element(ResourceType resource_type,const std::string & element_id)107 void ResourceProvider::invalidate_resource_element(
108 ResourceType resource_type,
109 const std::string& element_id) {
110
111 switch (resource_type) {
112
113 case ResourceType::TILESET:
114 {
115 tileset_cache.erase(element_id);
116 }
117 break;
118
119 default:
120 break;
121 }
122 }
123
124 }
125