Conquer Space 0.0.0
A space themed grand strategy game set in the near future, with realistic orbital mechanics, and an emphasis on economics and politics.
assetmanager.h
Go to the documentation of this file.
1/* Conquer Space
2 * Copyright (C) 2021-2023 Conquer Space
3 *
4 * This program 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 * This program 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
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18
19#include <hjson.h>
20#include <spdlog/spdlog.h>
21
22#include <istream>
23#include <map>
24#include <memory>
25#include <optional>
26#include <queue>
27#include <string>
28#include <utility>
29#include <vector>
30
31#include "engine/asset/asset.h"
35#include "engine/engine.h"
36#include "engine/enginelogger.h"
40#include "engine/gui.h"
41
42namespace cqsp {
43namespace asset {
48 public:
49 QueueHolder() { prototype = nullptr; }
50 explicit QueueHolder(AssetPrototype* type) : prototype(type) {}
51
53};
54
58template <typename T>
60 std::queue<T> queue_;
61 mutable std::mutex mutex_;
62
63 // Moved out of public interface to prevent races between this
64 // and pop().
65 bool empty() const { return queue_.empty(); }
66
67 public:
68 ThreadsafeQueue() = default;
71
73 std::lock_guard<std::mutex> lock(mutex_);
74 queue_ = std::move(other.queue_);
75 }
76
77 virtual ~ThreadsafeQueue() {}
78
79 unsigned long size() const {
80 std::lock_guard<std::mutex> lock(mutex_);
81 return queue_.size();
82 }
83
84 std::optional<T> pop() {
85 std::lock_guard<std::mutex> lock(mutex_);
86 if (queue_.empty()) {
87 return {};
88 }
89 T tmp = queue_.front();
90 queue_.pop();
91 return tmp;
92 }
93
94 void push(const T& item) {
95 std::lock_guard<std::mutex> lock(mutex_);
96 queue_.push(item);
97 }
98};
99
100class AssetLoader;
101class AssetManager;
102
103class Package {
104 public:
105 std::string name;
106 std::string version;
107 std::string title;
108 std::string author;
109
110 template <class T, typename V>
111 T* GetAsset(const V asset) {
112 if (!HasAsset(asset)) {
113 ENGINE_LOG_ERROR("Invalid key {}", asset);
114 }
115 return dynamic_cast<T*>(assets[asset].get());
116 }
117
118 bool HasAsset(const char* asset);
119 bool HasAsset(const std::string& asset);
120
121 auto begin() { return assets.begin(); }
122
123 auto end() { return assets.end(); }
124
125 private:
126 std::map<std::string, std::unique_ptr<Asset>> assets;
127
128 void ClearAssets();
129
130 friend class AssetLoader;
131 friend class AssetManager;
132};
133
135 public:
136 std::string name;
137 std::string version;
138 std::string title;
139 std::string author;
140 std::string path;
141
143};
144
146 public:
147 AssetManager() = default;
148
149 ShaderProgram_t MakeShader(const std::string& vert, const std::string& frag);
150 ShaderProgram_t MakeShader(const std::string& vert, const std::string& frag, const std::string& geom);
151
161 template <class T>
162 T* GetAsset(const std::string& key) {
163 static_assert(std::is_base_of<Asset, T>::value, "Class is not child of cqsp::asset::Asset");
164 std::size_t separation = key.find(":");
165 // Default name is core
166 std::string package_name = "core";
167 if (separation != std::string::npos) {
168 package_name = key.substr(0, separation);
169 }
170
171 // Check if package exists
172 if (packages.count(package_name) == 0) {
173 ENGINE_LOG_ERROR("Cannot find package {}", package_name);
174 return nullptr;
175 }
176 std::string pkg_key = key.substr(separation + 1, key.length());
177 auto& package = packages[package_name];
178 // Probably a better way to do this, to be honest
179 // Load default texture
180 if (!package->HasAsset(pkg_key)) {
181 ENGINE_LOG_ERROR("Cannot find asset {}", pkg_key);
182 if constexpr (std::is_same<T, asset::Texture>::value) {
183 return &empty_texture;
184 }
185 return nullptr;
186 }
187 // Check if asset exists
188 T* ptr = package->GetAsset<T>(pkg_key);
189 if (ptr == nullptr) {
190 SPDLOG_WARN("Asset {} is wrong type", key);
191 } else {
192 ptr->accessed++;
193 }
194 return ptr;
195 }
196
197 void LoadDefaultTexture();
198 void ClearAssets();
199
200 Package* GetPackage(const std::string& name) { return packages[name].get(); }
201
202 int GetPackageCount() { return packages.size(); }
203
204 auto begin() { return packages.begin(); }
205
206 auto end() { return packages.end(); }
207
208 void SaveModList();
209
210 std::map<std::string, PackagePrototype> m_package_prototype_list;
211
212 private:
213 std::map<std::string, std::unique_ptr<Package>> packages;
215 friend class AssetLoader;
216};
217
219 public:
220 AssetLoader();
221
227 void LoadMods();
228
259 std::unique_ptr<Package> LoadPackage(const std::string& path);
260
264 void BuildNextAsset();
265
270 bool QueueHasItems() { return m_asset_queue.size() != 0; }
271
276 std::vector<std::string>& GetMissingAssets() { return missing_assets; }
277
282 static std::string GetModFilePath();
283
284 std::atomic_int& getMaxLoading() { return max_loading; }
285 std::atomic_int& getCurrentLoading() { return currentloading; }
286
287 friend class AssetManager;
288
290
291 typedef std::function<std::unique_ptr<Asset>(cqsp::asset::VirtualMounter* mount, const std::string& path,
292 const std::string& key, const Hjson::Value& hints)>
294
295 private:
296 std::optional<PackagePrototype> LoadModPrototype(const std::string&);
297
303 std::unique_ptr<cqsp::asset::Asset> LoadText(cqsp::asset::VirtualMounter* mount, const std::string& path,
304 const std::string& key, const Hjson::Value& hints);
309 std::unique_ptr<cqsp::asset::Asset> LoadTextDirectory(cqsp::asset::VirtualMounter* mount, const std::string& path,
310 const std::string& key, const Hjson::Value& hints);
311
317 std::unique_ptr<cqsp::asset::Asset> LoadTexture(cqsp::asset::VirtualMounter* mount, const std::string& path,
318 const std::string& key, const Hjson::Value& hints);
319
323 std::unique_ptr<cqsp::asset::Asset> LoadBinaryAsset(cqsp::asset::VirtualMounter* mount, const std::string& path,
324 const std::string& key, const Hjson::Value& hints);
325
337 std::unique_ptr<cqsp::asset::Asset> LoadHjson(cqsp::asset::VirtualMounter* mount, const std::string& path,
338 const std::string& key, const Hjson::Value& hints);
339
345 std::unique_ptr<cqsp::asset::Asset> LoadShader(cqsp::asset::VirtualMounter* mount, const std::string& path,
346 const std::string& key, const Hjson::Value& hints);
355 std::unique_ptr<cqsp::asset::Asset> LoadFont(cqsp::asset::VirtualMounter* mount, const std::string& path,
356 const std::string& key, const Hjson::Value& hints);
363 std::unique_ptr<cqsp::asset::Asset> LoadAudio(cqsp::asset::VirtualMounter* mount, const std::string& path,
364 const std::string& key, const Hjson::Value& hints);
365
389 std::unique_ptr<cqsp::asset::Asset> LoadCubemap(cqsp::asset::VirtualMounter* mount, const std::string& path,
390 const std::string& key, const Hjson::Value& hints);
391
392 std::unique_ptr<cqsp::asset::Asset> LoadModel(cqsp::asset::VirtualMounter* mount, const std::string& path,
393 const std::string& key, const Hjson::Value& hints);
394
417 std::unique_ptr<ShaderDefinition> LoadShaderDefinition(cqsp::asset::VirtualMounter* mount, const std::string& path,
418 const std::string& key, const Hjson::Value& hints);
419
426 std::unique_ptr<TextDirectoryAsset> LoadScriptDirectory(VirtualMounter* mount, const std::string& path,
427 const Hjson::Value& hints);
428
437 std::unique_ptr<cqsp::asset::Asset> LoadAsset(const AssetType& type, const std::string& path,
438 const std::string& key, const Hjson::Value& hints);
439
440 ShaderProgram_t MakeShader(const std::string& key);
441
447 void PlaceAsset(Package& package, const AssetType& type, const std::string& path, const std::string& key,
448 const Hjson::Value& hints);
449
458 void LoadDirectory(const std::string& path, const std::function<void(std::string)>& file);
459
478 void LoadResources(Package& package, const std::string& path);
479
488 void LoadResourceHjsonFile(Package& package, const std::string& package_mount_path,
489 const std::string& resource_file_path, const Hjson::Value& asset_value);
497 bool HjsonPrototypeDirectory(Package& package, const std::string& path, const std::string& name);
498
504 IVirtualFileSystem* GetVfs(const std::string& path);
505
509 std::vector<std::string> missing_assets;
514
515 // All the assets that are to be loaded
516 std::atomic_int max_loading;
517
521 std::atomic_int currentloading;
526 std::map<AssetType, LoaderFunction> loading_functions;
528};
529} // namespace asset
530} // namespace cqsp
Definition: assetmanager.h:218
std::map< AssetType, LoaderFunction > loading_functions
The list of functions that are loading.
Definition: assetmanager.h:526
ThreadsafeQueue< QueueHolder > m_asset_queue
Queue for AssetPrototype when loading in frame.
Definition: assetmanager.h:513
ShaderProgram_t MakeShader(const std::string &key)
VirtualMounter mounter
Definition: assetmanager.h:527
std::function< std::unique_ptr< Asset >(cqsp::asset::VirtualMounter *mount, const std::string &path, const std::string &key, const Hjson::Value &hints)> LoaderFunction
Definition: assetmanager.h:293
std::vector< std::string > missing_assets
List of all assets that are missing
Definition: assetmanager.h:509
std::atomic_int currentloading
All the assets that have already been loaded
Definition: assetmanager.h:521
std::atomic_int & getCurrentLoading()
Definition: assetmanager.h:285
std::vector< std::string > & GetMissingAssets()
Gets the list of assets that were listed in the resource.hjson files, but were not found.
Definition: assetmanager.h:276
std::atomic_int max_loading
Definition: assetmanager.h:516
AssetManager * manager
Definition: assetmanager.h:289
bool QueueHasItems()
Checks if the queue has any remaining items to load on the main thread or not.
Definition: assetmanager.h:270
std::atomic_int & getMaxLoading()
Definition: assetmanager.h:284
Definition: assetmanager.h:145
std::map< std::string, PackagePrototype > m_package_prototype_list
Definition: assetmanager.h:210
friend class AssetLoader
Definition: assetmanager.h:215
ShaderProgram_t MakeShader(const std::string &vert, const std::string &frag)
Definition: assetmanager.cpp:63
std::map< std::string, std::unique_ptr< Package > > packages
Definition: assetmanager.h:213
T * GetAsset(const std::string &key)
Gets an asset.
Definition: assetmanager.h:162
void ClearAssets()
Definition: assetmanager.cpp:132
void LoadDefaultTexture()
Definition: assetmanager.cpp:121
Package * GetPackage(const std::string &name)
Definition: assetmanager.h:200
asset::Texture empty_texture
Definition: assetmanager.h:214
void SaveModList()
Definition: assetmanager.cpp:134
int GetPackageCount()
Definition: assetmanager.h:202
auto begin()
Definition: assetmanager.h:204
auto end()
Definition: assetmanager.h:206
Definition: assetprototype.h:37
The main functionality for this is to read files, so writing to files will not really be supported.
Definition: vfs.h:42
Definition: assetmanager.h:103
auto end()
Definition: assetmanager.h:123
auto begin()
Definition: assetmanager.h:121
std::string author
Definition: assetmanager.h:108
void ClearAssets()
Definition: assetmanager.cpp:56
std::string version
Definition: assetmanager.h:106
std::string name
Definition: assetmanager.h:105
std::string title
Definition: assetmanager.h:107
T * GetAsset(const V asset)
Definition: assetmanager.h:111
std::map< std::string, std::unique_ptr< Asset > > assets
Definition: assetmanager.h:126
bool HasAsset(const char *asset)
Definition: assetmanager.cpp:53
Definition: assetmanager.h:134
std::string author
Definition: assetmanager.h:139
std::string name
Definition: assetmanager.h:136
std::string version
Definition: assetmanager.h:137
std::string path
Definition: assetmanager.h:140
std::string title
Definition: assetmanager.h:138
bool enabled
Definition: assetmanager.h:142
Definition: assetmanager.h:47
QueueHolder()
Definition: assetmanager.h:49
QueueHolder(AssetPrototype *type)
Definition: assetmanager.h:50
AssetPrototype * prototype
Definition: assetmanager.h:52
Definition: texture.h:33
Definition: assetmanager.h:59
ThreadsafeQueue(const ThreadsafeQueue< T > &)=delete
void push(const T &item)
Definition: assetmanager.h:94
bool empty() const
Definition: assetmanager.h:65
std::optional< T > pop()
Definition: assetmanager.h:84
ThreadsafeQueue(ThreadsafeQueue< T > &&other)
Definition: assetmanager.h:72
unsigned long size() const
Definition: assetmanager.h:79
ThreadsafeQueue & operator=(const ThreadsafeQueue< T > &)=delete
virtual ~ThreadsafeQueue()
Definition: assetmanager.h:77
std::mutex mutex_
Definition: assetmanager.h:61
std::queue< T > queue_
Definition: assetmanager.h:60
Definition: vfs.h:155
lib tracy file(GLOB_RECURSE CPP_FILES *.cpp) list(FILTER CPP_FILES EXCLUDE REGEX ".*main.cpp$") file(GLOB_RECURSE H_FILES *.h) set(SOURCE_FILES $
Definition: CMakeLists.txt:22
#define ENGINE_LOG_ERROR(...)
Definition: enginelogger.h:31
AssetType
Definition: asset.h:31
std::shared_ptr< ShaderProgram > ShaderProgram_t
The preferred way of using a shader program.
Definition: shader.h:112
When adding assets, it is extremely crucial that you read cqsp::asset::AssetLoader::LoadResources to ...
Definition: clientctx.h:21