5#include <entt/entt.hpp>
10#include <unordered_map>
49 template <
typename Key,
typename AssetClass>
52 template <
typename Key,
typename AssetClass>
64 template <
typename Key,
typename AssetClass>
103 template <
typename Key,
typename AssetClass>
122 readyPromise = std::make_shared<std::promise<Result>>();
178 template <
typename Key,
typename AssetClass>
193 const auto record =
record_.lock();
194 return record ? record->state :
UNLOADED;
210 [[nodiscard]] AssetClass*
get()
const
212 const auto record =
record_.lock();
213 return record && record->state ==
LOADED ? record->asset.get() :
nullptr;
222 const auto record =
record_.lock();
223 return record ? record->generation : 0;
232 static const std::string empty;
233 const auto record =
record_.lock();
234 return record ? record->lastError : empty;
243 const auto record =
record_.lock();
251 [[nodiscard]]
explicit operator bool()
const
259 explicit Ref(std::shared_ptr<RecordType> record) :
record_(
std::move(record)) {}
263 static std::shared_future<Result> future = []
265 std::promise<Result> promise;
267 result.
error =
"Asset record expired";
268 promise.set_value(std::move(result));
269 return promise.get_future().share();
284 explicit AssetBase(
bool initializeDefaultEntity =
false) :
331 template <
typename Key,
typename AssetClass>
347 template <
typename... Args>
355 void add(Key path, AssetClass* asset);
375 void resolve(
const Key& path, std::unique_ptr<AssetClass> asset);
380 void fail(
const Key& path, std::string error);
414 std::optional<AssetClass*>
getAsset(
const Key& path);
426 template<
typename Func>
428 for (
const auto& [key, record] :
records) {
429 if (record && record->asset !=
nullptr) {
430 func(key, record->asset.get());
437 [[nodiscard]] std::shared_ptr<RecordType>
getRecord(
const Key& path)
const;
438 void completeRecord(
const std::shared_ptr<RecordType>& record,
bool success, std::string error = {});
441 std::unordered_map<Key, std::shared_ptr<RecordType>>
records;
444 template<
typename Key,
typename AssetClass>
445 template<
typename... Args>
448 record->asset = std::make_unique<AssetClass>(std::forward<Args>(args)...);
449 ++record->generation;
450 record->resetFuture();
452 if (record->state ==
LOADED) {
457 template<
typename Key,
typename AssetClass>
460 assert(asset !=
nullptr);
462 record->asset.reset(asset);
463 ++record->generation;
464 record->resetFuture();
466 if (record->state ==
LOADED) {
471 template<
typename Key,
typename AssetClass>
476 template<
typename Key,
typename AssetClass>
481 template<
typename Key,
typename AssetClass>
488 ++record->generation;
489 record->resetFuture();
490 record->lastError.clear();
492 record->asset.reset();
496 record->state = state;
502 template<
typename Key,
typename AssetClass>
505 record->asset = std::move(asset);
507 record->lastError.clear();
511 template<
typename Key,
typename AssetClass>
514 record->asset.reset();
516 record->lastError = std::move(error);
520 template<
typename Key,
typename AssetClass>
524 record->asset.reset();
526 ++record->generation;
527 record->resetFuture();
528 record->lastError.clear();
531 template<
typename Key,
typename AssetClass>
534 return record && record->asset !=
nullptr;
537 template <
typename Key,
typename AssetClass>
543 template <
typename Key,
typename AssetClass>
548 return record->state;
551 template<
typename Key,
typename AssetClass>
555 if (!record || record->asset ==
nullptr)
return std::nullopt;
557 return record->asset.get();
560 template <
typename Key,
typename AssetClass>
564 for (
auto& [key, record] :
records)
568 record->asset.reset();
570 ++record->generation;
571 record->resetFuture();
572 record->lastError.clear();
578 template<
typename Key,
typename AssetClass>
585 auto record = std::make_shared<RecordType>(path);
590 template<
typename Key,
typename AssetClass>
592 const auto it =
records.find(path);
593 return it !=
records.end() ? it->second :
nullptr;
596 template<
typename Key,
typename AssetClass>
598 if (!record || record->readyPromiseResolved || !record->readyPromise)
return;
602 result.
asset = success ? record->asset.get() :
nullptr;
604 result.
error = std::move(error);
607 record->readyPromise->set_value(std::move(result));
608 record->readyPromiseResolved =
true;
611 template<
typename Key,
typename AssetClass>
613 if (!record || record->asset ==
nullptr)
return;
614 if (record->state ==
FAILED)
return;
616 const LoadState payloadState = record->asset->getLoadingState();
617 if (payloadState != record->state) {
618 record->state = payloadState;
620 if (record->state ==
LOADED) {
#define TRACY_ZONE_SCOPED_NAMED(name)
void requestLoad()
If this asset is in the UNLOADED state it will get added to the assets to load.
entt::entity getEntity() const
Getter for data.
virtual void unload()
Base function for unloading the ecs data.
AssetBase(bool initializeDefaultEntity=false)
virtual void updateLoadingState()
CpuLoadingState loadingState
CpuLoadingState getLoadingState()
Gets the loading state of this asset.
entt::registry & mainRegistry
A manager which is used to look up existing assets and their loading state.
void declare(Key path, Args &&... args)
Adds an asset to the list in its unloaded state.
std::shared_ptr< RecordType > getOrCreateRecord(const Key &path)
Record< Key, AssetClass > RecordType
LoadResult< Key, AssetClass > ResultType
CpuLoadingState getAssetLoadingState(const Key &path)
Gets a loading state for an asset. If the asset is not yet declared it will return that it is UNLOADE...
std::optional< AssetClass * > getAsset(const Key &path)
Try's to get an asset. If the asset does not exist (can be checked with exists) it will return a std:...
void syncRecordStateFromPayload(const std::shared_ptr< RecordType > &record) const
void setAssetLoadingState(const Key &path, LoadState state)
Sets the record loading state without requiring a payload object.
void fail(const Key &path, std::string error)
Marks the record as failed and resolves the ready future with an error.
std::shared_ptr< RecordType > getRecord(const Key &path) const
bool isDeclared(Key path)
Checks if an asset has been declared. If it exists it is also declared.
void forEachAsset(Func &&func) const
Iterates over all assets and calls the provided callback for each.
void completeRecord(const std::shared_ptr< RecordType > &record, bool success, std::string error={})
bool exists(Key path)
Checks if an asset already exists. This means it is declared and there is content.
virtual void clear()
Clears out all resources.
void add(Key path, AssetClass *asset)
Adds or overwrites a previously declared asset at a key.
RefType getRef(const Key &path) const
Gets a stable asset reference if a record exists, otherwise an expired ref.
virtual ~AssetManager()=default
Ref< Key, AssetClass > RefType
void resolve(const Key &path, std::unique_ptr< AssetClass > asset)
Stores a loaded payload and resolves the record's ready future.
std::unordered_map< Key, std::shared_ptr< RecordType > > records
void unloadAssetPayload(const Key &path)
Drops the loaded payload while preserving the stable record.
RefType getOrCreateRef(const Key &path)
Gets a stable asset reference, creating a record if necessary.
Non-owning handle to an asset record managed by AssetManager.
LoadState getState() const
Gets the current loading state.
Ref(std::shared_ptr< RecordType > record)
LoadResult< Asset::MeshPath, Animation > Result
const std::string & getError() const
Gets the last load error reported by the record.
std::shared_future< Result > readyFuture() const
Gets a future for completion of the current generation.
std::weak_ptr< RecordType > record_
static std::shared_future< Result > expiredFuture()
bool isLoaded() const
Checks whether the referenced asset has a loaded payload.
AssetClass * get() const
Gets the loaded payload.
Record< Asset::MeshPath, Animation > RecordType
uint64_t getGeneration() const
Gets the current record generation.
Classes which are related to asset loading are mostly stored in this namespace.
CpuLoadingState
State for assets in the asset loading process.
@ LOADED
All components of the asset have been loaded, and it is ready to be used.
@ REQUESTED_LOAD
An asset has been requested to load and is waiting for an asset pipeline to start working on it.
@ LOADING
While the asset is currently being processed in the asset pipeline.
@ UNLOADED
When the asset is not loaded yet but the frame is already existing for the heavy data to be loaded in...
@ FAILED
Asset loading finished unsuccessfully. Inspect the asset ref error for details.
CpuLoadingState LoadState
Data structs for the Entity Component System.
Result returned when an asynchronous asset load reaches a terminal state.
AssetClass * asset
Loaded asset payload, or nullptr when loading failed or the record expired.
bool success
True when the payload finished loading successfully.
Ref< Key, AssetClass > ref
Stable reference to the record that produced this result.
std::string error
Failure message for unsuccessful loads.
uint64_t generation
Record generation that completed.
Internal storage for one asset entry managed by AssetManager.
std::string lastError
Last failure message reported for this record.
std::shared_future< Result > readyFuture
Shared future resolved when the current generation succeeds or fails.
Record(Key key)
Creates an unloaded record for an asset key.
void resetFuture()
Starts a new ready future for the current generation.
bool readyPromiseResolved
True after readyPromise has been resolved for the current generation.
uint64_t generation
Monotonic version incremented when the payload lifecycle restarts.
std::shared_ptr< std::promise< Result > > readyPromise
Promise used by AssetManager to complete readyFuture.
LoadState state
Current CPU loading state for the record.
LoadResult< Key, AssetClass > Result
Key key
Asset lookup key for this record.
std::unique_ptr< AssetClass > asset
Owned payload instance, or nullptr while no payload is available.