Unravel Engine C++ Reference
Loading...
Searching...
No Matches
asset_manager.h
Go to the documentation of this file.
1#pragma once
2#include <engine/engine_export.h>
3
4#include "asset_flags.h"
5#include "asset_storage.h"
6#include <cassert>
7#include <map>
8#include <mutex>
9#include <unordered_map>
10
11namespace unravel
12{
13
19{
20public:
26
31
36 void set_parent(asset_manager* parent);
37
43 auto init(rtti::context& ctx) -> bool;
44
50 auto deinit(rtti::context& ctx) -> bool;
51
55 void unload_all();
56
61 void unload_group(const std::string& group);
62
68 auto load_database(const std::string& protocol) -> bool;
69
75 void save_database(const std::string& protocol, const fs::path& path);
76
81 void remove_asset_info_for_path(const fs::path& path);
82
87 void remove_asset_info_for_key(const std::string& key);
88
89
96 auto add_asset_info_for_path(const fs::path& path, const asset_meta& meta, bool override) -> hpp::uuid;
97
104 auto add_asset_info_for_key(const std::string& key, const asset_meta& meta, bool override) -> hpp::uuid;
105
111 auto get_metadata(const hpp::uuid& uid) const -> asset_database::meta;
112 auto generate_metadata(const fs::path& p) const -> asset_meta;
113
121 template<typename S, typename... Args>
122 auto add_storage(Args&&... args) -> asset_storage<S>&
123 {
124 auto operation = storages_.emplace(hpp::type_id<asset_storage<S>>().hash_code(),
125 std::make_unique<asset_storage<S>>(std::forward<Args>(args)...));
126
127 return static_cast<asset_storage<S>&>(*operation.first->second);
128 }
129
137 template<typename T>
138 auto get_asset(const std::string& key, load_flags flags = load_flags::standard) -> asset_handle<T>
139 {
140 auto& storage = get_storage<T>();
141 return load_asset_from_file_impl<T>(key,
142 flags,
143 storage.container_mutex,
144 storage.container,
145 storage.load_from_file);
146 }
147
155 template<typename T>
156 auto get_asset(const hpp::uuid& uid, load_flags flags = load_flags::standard) -> asset_handle<T>
157 {
158 auto meta = get_metadata(uid);
159 if(!meta.location.empty())
160 {
161 const auto& key = meta.location;
162 return get_asset<T>(key, flags);
163 }
164
165 if(parent_)
166 {
167 return parent_->get_asset<T>(uid, flags);
168 }
169 return {};
170 }
171
178 template<typename T>
179 auto find_asset(const std::string& key) const -> const asset_handle<T>&
180 {
181 auto& storage = get_storage<T>();
182 return find_asset_impl<T>(key, storage.container_mutex, storage.container);
183 }
184
192 template<typename T>
193 auto get_asset_from_instance(const std::string& key, std::shared_ptr<T> entry) -> asset_handle<T>
194 {
195 auto& storage = get_storage<T>();
196 return get_asset_from_instance_impl(key,
197 entry,
198 storage.container_mutex,
199 storage.container,
200 storage.load_from_instance);
201 }
202
209 template<typename T>
210 void rename_asset(const std::string& key, const std::string& new_key)
211 {
212 for(auto& kvp : databases_)
213 {
214 auto& db = kvp.second;
215 db.rename_asset(key, new_key);
216 }
217
218 auto& storage = get_storage<T>();
219
220 std::lock_guard<std::recursive_mutex> lock(storage.container_mutex);
221 auto it = storage.container.find(key);
222 if(it != storage.container.end())
223 {
224 auto& handle = it->second;
225 handle.set_internal_id(new_key);
226 storage.container[new_key] = handle;
227 storage.container.erase(it);
228 }
229
230 if(parent_)
231 {
232 parent_->rename_asset<T>(key, new_key);
233 }
234 }
235
241 template<typename T>
242 void unload_asset(const std::string& key)
243 {
244 auto& storage = get_storage<T>();
245 storage.unload_single(pool_, key);
246
247 if(parent_)
248 {
249 parent_->unload_asset<T>(key);
250 }
251 }
252
259 template<typename T>
260 auto get_assets(const std::string& group = {}) const -> std::vector<asset_handle<T>>
261 {
262 auto& storage = get_storage<T>();
263 auto assets = storage.get_group(group);
264
265 if(parent_)
266 {
267 auto passets = parent_->get_assets<T>(group);
268 std::move(std::begin(passets), std::end(passets), std::back_inserter(assets));
269 }
270
271 return assets;
272 }
273
281 template<typename T, typename F>
282 auto get_assets_with_predicate(F&& predicate) const -> std::vector<asset_handle<T>>
283 {
284 auto& storage = get_storage<T>();
285 return storage.get_with_condition(std::forward<F>(predicate));
286 }
287
294 template<typename T, typename F>
295 void for_each_asset(F&& callback)
296 {
297 auto& storage = get_storage<T>();
298 std::lock_guard<std::recursive_mutex> lock(storage.container_mutex);
299
300 for(const auto& el : storage.container)
301 {
302 callback(el);
303 }
304
305 if(parent_)
306 {
307 parent_->for_each_asset<T, F>(std::forward<F>(callback));
308 }
309 }
310
311private:
317 auto get_database(const std::string& group) -> asset_database&;
318
323 void remove_database(const std::string& group);
324
330 auto add_asset(const std::string& key) -> hpp::uuid;
331
343 template<typename T, typename F>
344 auto load_asset_from_file_impl(const std::string& key,
345 load_flags flags,
346 std::recursive_mutex& container_mutex,
347 typename asset_storage<T>::request_container_t& container,
348 F&& load_func) -> asset_handle<T>
349 {
350 if(flags != load_flags::reload)
351 {
352 auto inst = find_asset_impl<T>(key, container_mutex, container);
353 if(inst)
354 {
355 return inst;
356 }
357 }
358
359 std::unique_lock<std::recursive_mutex> lock(container_mutex);
360
361 auto& handle = container[key];
362 // Dispatch the loading
363 if(load_func)
364 {
365 auto uid = add_asset(key);
366 // calling the function on a locked mutex is ok
367 // since we dont expect this to actually
368 // do much except add tasks to the executor
369
370 if(handle.task_id())
371 {
372 pool_.stop(handle.task_id());
373 handle.invalidate();
374 }
375
376 handle.set_internal_ids(uid, key);
377 load_func(pool_, handle, key);
378 }
379
380 return handle;
381 }
382
394 template<typename T, typename F>
395 auto get_asset_from_instance_impl(const std::string& key,
396 std::shared_ptr<T> entry,
397 std::recursive_mutex& container_mutex,
398 typename asset_storage<T>::request_container_t& container,
399 F&& load_func) -> asset_handle<T>
400 {
401 auto inst = find_asset_impl<T>(key, container_mutex, container);
402 if(inst)
403 {
404 return inst;
405 }
406
407 std::lock_guard<std::recursive_mutex> lock(container_mutex);
408
409 auto& handle = container[key];
410 // Dispatch the loading
411 if(load_func)
412 {
413 auto uid = add_asset(key);
414
415 // loading on a locked mutex is ok
416 // since we dont expect this to actually
417 // do much except add tasks to the
418 // executor
419 handle.set_internal_ids(uid, key);
420 load_func(pool_, handle, entry);
421 }
422
423 return handle;
424 }
425
434 template<typename T>
435 auto find_asset_impl(const std::string& key,
436 std::recursive_mutex& container_mutex,
437 typename asset_storage<T>::request_container_t& container) const -> const asset_handle<T>&
438 {
439 std::lock_guard<std::recursive_mutex> lock(container_mutex);
440 auto it = container.find(key);
441 if(it != container.end())
442 {
443 return it->second;
444 }
445
446 if(parent_)
447 {
448 return parent_->find_asset_impl<T>(key, container_mutex, container);
449 }
450
452 }
453
459 template<typename S>
460 auto get_storage() -> asset_storage<S>&
461 {
462 auto it = storages_.find(hpp::type_id<asset_storage<S>>().hash_code());
463 assert(it != storages_.end());
464 return (static_cast<asset_storage<S>&>(*it->second.get()));
465 }
466
472 template<typename S>
473 auto get_storage() const -> asset_storage<S>&
474 {
475 auto& storage = storages_.at(hpp::type_id<asset_storage<S>>().hash_code());
476 return (static_cast<asset_storage<S>&>(*storage.get()));
477 }
478
480 tpp::thread_pool& pool_;
482 std::unordered_map<std::size_t, std::unique_ptr<basic_storage>> storages_{};
484 mutable std::mutex db_mutex_;
486 std::map<std::string, asset_database, std::less<>> databases_{};
488 asset_manager* parent_{};
489};
490
491} // namespace unravel
Manages asset metadata and provides functionality for adding, removing, and querying assets.
Manages assets, including loading, unloading, and storage.
auto load_database(const std::string &protocol) -> bool
Loads an asset database from a protocol.
void save_database(const std::string &protocol, const fs::path &path)
Saves the asset database to a specified path.
asset_manager(rtti::context &ctx)
Constructs an asset manager with the given context.
auto generate_metadata(const fs::path &p) const -> asset_meta
void unload_all()
Unloads all assets.
auto init(rtti::context &ctx) -> bool
Initializes the asset manager with the given context.
~asset_manager()
Destructs the asset manager.
auto get_asset(const hpp::uuid &uid, load_flags flags=load_flags::standard) -> asset_handle< T >
Gets an asset by its UUID.
void unload_asset(const std::string &key)
Unloads an asset by its key.
void for_each_asset(F &&callback)
Applies a callback function to each asset.
auto get_metadata(const hpp::uuid &uid) const -> asset_database::meta
Gets metadata for a resource uid.
auto get_assets_with_predicate(F &&predicate) const -> std::vector< asset_handle< T > >
Gets all assets that satisfy a predicate.
auto deinit(rtti::context &ctx) -> bool
Deinitializes the asset manager with the given context.
auto add_storage(Args &&... args) -> asset_storage< S > &
Adds a storage for a specific type.
auto get_asset(const std::string &key, load_flags flags=load_flags::standard) -> asset_handle< T >
Gets an asset by its key.
auto get_assets(const std::string &group={}) const -> std::vector< asset_handle< T > >
Gets all assets in a specified group.
void remove_asset_info_for_key(const std::string &key)
Removes asset information for a specified key.
auto add_asset_info_for_key(const std::string &key, const asset_meta &meta, bool override) -> hpp::uuid
Adds asset information for a specified key.
auto add_asset_info_for_path(const fs::path &path, const asset_meta &meta, bool override) -> hpp::uuid
Adds asset information for a specified path.
void remove_asset_info_for_path(const fs::path &path)
Removes asset information for a specified path.
auto find_asset(const std::string &key) const -> const asset_handle< T > &
Finds an asset by its key.
void rename_asset(const std::string &key, const std::string &new_key)
Renames an asset.
void unload_group(const std::string &group)
Unloads all assets in a specified group.
void set_parent(asset_manager *parent)
Sets the parent asset manager.
auto get_asset_from_instance(const std::string &key, std::shared_ptr< T > entry) -> asset_handle< T >
Gets an asset handle from an instance.
Represents a handle to an asset, providing access and management functions.
static auto get_empty() -> const asset_handle &
Gets an empty asset handle.
Metadata information for an asset including its location.
Metadata for an asset, including its UUID and type.
Manages storage and loading of assets of a specific type.
std::unordered_map< std::string, asset_handle< T > > request_container_t
Container for asset requests.
gfx::uniform_handle handle
Definition uniform.cpp:9