asge::game::asset::AssetManager
Owns the per-asset-type AssetPools and resolves/loads through a VirtualFileSystem the caller keeps alive.
#include <AssetManager.hpp>The one entry point for loading assets by virtual path: GetImage/ GetFont/GetFrameTable/GetAudio each forward to their own AssetPool, which caches by virtual path (plus, for fonts, the bake pixel height) and only calls the underlying Load on a cache miss. ResolveAssets builds on these to deferred-load an entire Registry's worth of components in one pass, dispatching per component type through Resolver<T> — see its own doc comment. Does not own inVfs — it must outlive the AssetManager.
Private Types
Private Attributes
std::unordered_map< media::Font const *, std::unique_ptr< video::ITexture > > m_FontAtlasCacheprivatePublic Member Functions
explicit AssetManager(filesystem::VirtualFileSystem const &inVfs) noexceptAssetManager(AssetManager const &)=deleteAssetManager & operator=(AssetManager const &)=deleteAssetManager(AssetManager &&)=defaultAssetManager & operator=(AssetManager &&)=delete~AssetManager()=defaultResult< asset_ptr< media::Image > > GetImage(str::StringCRef inVirtualPath)Loads (or returns the cached) Image at a virtual path.
Fails if the path doesn't resolve through the VFS or fails to decode.
Result< asset_ptr< media::Font > > GetFont(str::StringCRef inVirtualPath, int inPixelHeight)Loads (or returns the cached) Font baked at inPixelHeight.
A different inPixelHeight for the same path is a separate cache entry.
Result< asset_ptr< FrameTable > > GetFrameTable(str::StringCRef inVirtualPath)Loads (or returns the cached) FrameTable at a virtual path — the meta-file a components::Animation::m_ClipPath points at.
Result< asset_ptr< media::AudioClip > > GetAudio(str::StringCRef inVirtualPath)Loads (or returns the cached) AudioClip at a virtual path.
Fails if the path doesn't resolve through the VFS or fails to decode.
Result< video::ITexture * > GetTexture(str::StringCRef inVirtualPath, video::IRenderer &inRenderer) noexceptLoads (or returns the cached) GPU texture for a virtual path, creating it via inRenderer on first request.
Cached by virtual path like GetImage — later calls for the same path return the same ITexture* rather than allocating a new one. A failed image resolve/decode or texture creation is returned as-is and nothing is cached, so a later call retries.
Frees the GPU texture cached for inVirtualPath, if any.
No-op if nothing is cached for that path; a later GetTexture() call recreates it.
Drops the decoded Image and GPU texture cached for inVirtualPath and un-resolves every Sprite in inRegistry using it.
The next ResolveAssets() re-reads the file from disk, so those sprites pick up its new pixels instead of the stale cached ones.
Result< video::ITexture * > GetFontAtlasTexture(media::Font const &inFont, video::IRenderer &inRenderer) noexceptLoads (or returns the cached) GPU texture for inFont's baked glyph atlas, creating it via inRenderer on first request.
Cached by Font address (see m_FontAtlasCache's own doc comment), not a virtual path there is no separate atlas image file to load, the atlas is already decoded in memory as part of inFont. A failed texture creation is returned as-is and nothing is cached, so a later call retries.
Deferred-loads every asset-owning component in inRegistry whose asset still needs (re)resolving, for every entity that has one.
Folds over components::SerializableComponents and, for each type T, calls Resolver<T>{} on every entity's T — a no-op for most component types (nothing to load), and an actual resolve for the ones that do own an asset (Sprite, Animation, AudioSource — re-resolved whenever their virtual path changes, released back to null when it's cleared to empty; PathFollow builds its path once — see their own Resolver<T> specializations in AssetResolver.hpp for exactly what each one does).
Any resolve failure (VFS resolve, decode, texture creation) is logged and that entity is left unresolved — retried on the next call rather than treated as fatal, since inRenderer only exists once the caller has a window (unlike component construction, which can happen earlier, e.g. while loading a scene).
Walks every entity via View<Ts>().IncludeDisabled(), not the disabled-skipping View<Ts>() every gameplay system uses — a markers::Disabled entity should already have a live texture/clip ready the instant something re-enables it, not still be waiting on some unrelated future resolve to notice it exists.