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.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
assetmanager.h
Go to the documentation of this file.
1/* Conquer Space
2 * Copyright (C) 2021-2025 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 ptr->PostLoad(*this);
195 return ptr;
196 }
197
198 void LoadDefaultTexture();
199 void ClearAssets();
200
201 Package* GetPackage(const std::string& name) { return packages[name].get(); }
202
203 int GetPackageCount() { return packages.size(); }
204
205 auto begin() { return packages.begin(); }
206
207 auto end() { return packages.end(); }
208
209 void SaveModList();
210
211 std::map<std::string, PackagePrototype> m_package_prototype_list;
212
213 private:
214 std::map<std::string, std::unique_ptr<Package>> packages;
216 friend class AssetLoader;
217};
218
220 public:
221 AssetLoader();
222
228 void LoadMods();
229
260 std::unique_ptr<Package> LoadPackage(const std::string& path);
261
265 void BuildNextAsset();
266
271 bool QueueHasItems() { return m_asset_queue.size() != 0; }
272
277 std::vector<std::string>& GetMissingAssets() { return missing_assets; }
278
283 static std::string GetModFilePath();
284
285 std::atomic_int& getMaxLoading() { return max_loading; }
286 std::atomic_int& getCurrentLoading() { return currentloading; }
287
288 friend class AssetManager;
289
291
292 typedef std::function<std::unique_ptr<Asset>(cqsp::asset::VirtualMounter* mount, const std::string& path,
293 const std::string& key, const Hjson::Value& hints)>
295
296 private:
297 std::optional<PackagePrototype> LoadModPrototype(const std::string&);
298
304 std::unique_ptr<cqsp::asset::Asset> LoadText(cqsp::asset::VirtualMounter* mount, const std::string& path,
305 const std::string& key, const Hjson::Value& hints);
310 std::unique_ptr<cqsp::asset::Asset> LoadTextDirectory(cqsp::asset::VirtualMounter* mount, const std::string& path,
311 const std::string& key, const Hjson::Value& hints);
312
318 std::unique_ptr<cqsp::asset::Asset> LoadTexture(cqsp::asset::VirtualMounter* mount, const std::string& path,
319 const std::string& key, const Hjson::Value& hints);
320
324 std::unique_ptr<cqsp::asset::Asset> LoadBinaryAsset(cqsp::asset::VirtualMounter* mount, const std::string& path,
325 const std::string& key, const Hjson::Value& hints);
326
338 std::unique_ptr<cqsp::asset::Asset> LoadHjson(cqsp::asset::VirtualMounter* mount, const std::string& path,
339 const std::string& key, const Hjson::Value& hints);
340
346 std::unique_ptr<cqsp::asset::Asset> LoadShader(cqsp::asset::VirtualMounter* mount, const std::string& path,
347 const std::string& key, const Hjson::Value& hints);
356 std::unique_ptr<cqsp::asset::Asset> LoadFont(cqsp::asset::VirtualMounter* mount, const std::string& path,
357 const std::string& key, const Hjson::Value& hints);
364 std::unique_ptr<cqsp::asset::Asset> LoadAudio(cqsp::asset::VirtualMounter* mount, const std::string& path,
365 const std::string& key, const Hjson::Value& hints);
366
390 std::unique_ptr<cqsp::asset::Asset> LoadCubemap(cqsp::asset::VirtualMounter* mount, const std::string& path,
391 const std::string& key, const Hjson::Value& hints);
392
393 std::unique_ptr<cqsp::asset::Asset> LoadModel(cqsp::asset::VirtualMounter* mount, const std::string& path,
394 const std::string& key, const Hjson::Value& hints);
395
418 std::unique_ptr<ShaderDefinition> LoadShaderDefinition(cqsp::asset::VirtualMounter* mount, const std::string& path,
419 const std::string& key, const Hjson::Value& hints);
420
427 std::unique_ptr<TextDirectoryAsset> LoadScriptDirectory(VirtualMounter* mount, const std::string& path,
428 const Hjson::Value& hints);
429
438 std::unique_ptr<cqsp::asset::Asset> LoadAsset(const AssetType& type, const std::string& path,
439 const std::string& key, const Hjson::Value& hints);
440
441 ShaderProgram_t MakeShader(const std::string& key);
442
448 void PlaceAsset(Package& package, const AssetType& type, const std::string& path, const std::string& key,
449 const Hjson::Value& hints);
450
459 void LoadDirectory(const std::string& path, const std::function<void(std::string)>& file);
460
479 void LoadResources(Package& package, const std::string& path);
480
489 void LoadResourceHjsonFile(Package& package, const std::string& package_mount_path,
490 const std::string& resource_file_path, const Hjson::Value& asset_value);
498 bool HjsonPrototypeDirectory(Package& package, const std::string& path, const std::string& name);
499
505 IVirtualFileSystem* GetVfs(const std::string& path);
506
510 std::vector<std::string> missing_assets;
515
516 // All the assets that are to be loaded
517 std::atomic_int max_loading;
518
522 std::atomic_int currentloading;
527 std::map<AssetType, LoaderFunction> loading_functions;
529};
530} // namespace asset
531} // namespace cqsp
Definition: assetmanager.h:219
std::map< AssetType, LoaderFunction > loading_functions
The list of functions that are loading.
Definition: assetmanager.h:527
ThreadsafeQueue< QueueHolder > m_asset_queue
Queue for AssetPrototype when loading in frame.
Definition: assetmanager.h:514
ShaderProgram_t MakeShader(const std::string &key)
VirtualMounter mounter
Definition: assetmanager.h:528
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:294
std::vector< std::string > missing_assets
List of all assets that are missing
Definition: assetmanager.h:510
std::atomic_int currentloading
All the assets that have already been loaded
Definition: assetmanager.h:522
std::atomic_int & getCurrentLoading()
Definition: assetmanager.h:286
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:277
std::atomic_int max_loading
Definition: assetmanager.h:517
AssetManager * manager
Definition: assetmanager.h:290
bool QueueHasItems()
Checks if the queue has any remaining items to load on the main thread or not.
Definition: assetmanager.h:271
std::atomic_int & getMaxLoading()
Definition: assetmanager.h:285
Definition: assetmanager.h:145
std::map< std::string, PackagePrototype > m_package_prototype_list
Definition: assetmanager.h:211
friend class AssetLoader
Definition: assetmanager.h:216
ShaderProgram_t MakeShader(const std::string &vert, const std::string &frag)
Definition: assetmanager.cpp:65
std::map< std::string, std::unique_ptr< Package > > packages
Definition: assetmanager.h:214
T * GetAsset(const std::string &key)
Gets an asset.
Definition: assetmanager.h:162
void ClearAssets()
Definition: assetmanager.cpp:137
void LoadDefaultTexture()
Definition: assetmanager.cpp:126
Package * GetPackage(const std::string &name)
Definition: assetmanager.h:201
asset::Texture empty_texture
Definition: assetmanager.h:215
void SaveModList()
Definition: assetmanager.cpp:139
int GetPackageCount()
Definition: assetmanager.h:203
auto begin()
Definition: assetmanager.h:205
auto end()
Definition: assetmanager.h:207
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:58
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:55
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:33
std::shared_ptr< ShaderProgram > ShaderProgram_t
The preferred way of using a shader program.
Definition: shader.h:114
When adding assets, it is extremely crucial that you read cqsp::asset::AssetLoader::LoadResources to ...
Definition: clientctx.h:22