Polyphase Game Engine
Loading...
Searching...
No Matches
AssetManager.h
Go to the documentation of this file.
1#pragma once
2
3#include "Asset.h"
4#include "AssetRef.h"
5#include "Log.h"
6
7#include "System/System.h"
8
9#include <string>
10#include <deque>
11#include <unordered_map>
12
13class Asset;
14class AssetDir;
15class Material;
16class ParticleSystem;
17
19{
20 std::string mName;
21 std::string mPath;
22 uint64_t mUuid = 0; // For UUID-based loading
23 std::vector<AssetRef*> mTargetRefs;
24 std::vector<AssetStub*> mDependentAssets;
25 const EmbeddedFile* mEmbeddedData = nullptr;
27 Asset* mAsset = nullptr;
28 int32_t mRequeueCount = 0;
29};
30
31#if EDITOR
32// Discovered non-.oct file (e.g. .mp4, .json, .png) tracked for packaging.
33// Raw files are invisible to the runtime asset system; this registry only
34// exists to drive packaging-time copy / embed decisions.
35//
36// mAbsolutePath follows the same convention as AssetStub::mPath:
37// - engine asset: "Engine/Assets/<...>" (relative to CWD; engine source dir is co-located)
38// - project asset: absolute path under projectDir, e.g. "M:/.../MyProject/Assets/<...>"
39// - addon asset: absolute path under projectDir/Packages, e.g. "M:/.../MyProject/Packages/<addon>/Assets/<...>"
40// The packaging code at ActionManager.cpp derives the destination by mirroring
41// saveDir's projectDir-prefix-strip rule: routing engine/project/addon paths
42// follows the same logic as cooked .oct files.
43struct RawAssetEntry
44{
45 std::string mAbsolutePath;
46 bool mEngineAsset = false;
47 uint32_t mPlatformMask = PlatformBit_All;
48 bool mEmbed = false;
49};
50
51// Result of reading an {asset}.meta sidecar. mExists is false when no sidecar
52// is present on disk; in that case the other fields hold their defaults.
53struct AssetMetaSidecar
54{
55 uint32_t mPlatformMask = PlatformBit_All;
56 bool mEmbed = false;
57 bool mExists = false;
58};
59#endif
60
61// Name-based lookup (backward compatible)
62POLYPHASE_API Asset* FetchAsset(const std::string& name);
63POLYPHASE_API Asset* LoadAsset(const std::string& name);
64POLYPHASE_API void UnloadAsset(const std::string& name);
65POLYPHASE_API void AsyncLoadAsset(const std::string& name, AssetRef* targetRef = nullptr);
66POLYPHASE_API AssetStub* FetchAssetStub(const std::string& name);
67
68// UUID-based lookup
70POLYPHASE_API Asset* LoadAssetByUuid(uint64_t uuid);
71POLYPHASE_API void AsyncLoadAssetByUuid(uint64_t uuid, AssetRef* targetRef = nullptr);
73
74#if EDITOR
75// Editor-only: addon-provided source-extension dispatch. Addons call this from
76// their plugin OnLoad to teach ActionManager::ImportAsset which Asset subclass
77// owns a given source-file extension (e.g. ".mp4" -> VideoClip). The extension
78// must include the leading dot and be lowercase; comparisons in the dispatcher
79// are case-sensitive to match the existing built-in branches.
80POLYPHASE_API void RegisterImportExtension(const std::string& ext, TypeId type);
81POLYPHASE_API TypeId LookupImportExtension(const std::string& ext);
82
83// Returns the AssetDir the user is currently browsing in the asset browser —
84// i.e. the folder a right-click → "Create Asset" should write into. Returns
85// nullptr if no project is open or the editor isn't ready yet.
86//
87// Exposed for native addons that surface custom asset types in the asset
88// browser's New Asset menu (via EditorUIHooks::AddCreateAssetItem(s)) and
89// want the created asset to land in the user's current folder. Wraps
90// GetEditorState()->GetAssetDirectory() so addons don't have to take a
91// dependency on the non-exported EditorState class.
92POLYPHASE_API AssetDir* GetCurrentAssetDir();
93#endif
94
95template<typename T>
96T* FetchAsset(const std::string& name)
97{
98 Asset* asset = FetchAsset(name);
99
100 if (asset != nullptr &&
101 asset->GetType() != T::GetStaticType())
102 {
103 LogError("Type mismatch in FetchAsset<T>()");
104 asset = nullptr;
105 }
106
107 return (T*)asset;
108}
109
110template<typename T>
111T* LoadAsset(const std::string& name)
112{
113 Asset* asset = LoadAsset(name);
114
115 if (asset != nullptr &&
116 !asset->Is(T::ClassRuntimeId()))
117 {
118 LogError("Type mismatch in LoadAsset<T>()");
119 asset = nullptr;
120 }
121
122 return (T*)asset;
123}
124
125// Per-method POLYPHASE_API on the addon-facing surface only. A class-level
126// export expands to dllexport on every member (incl. implicit special-member
127// instantiations in TUs that only forward-decl AssetManager members), which
128// risks C4150 against forward-declared types. The addon-facing surface is:
129// - Get()
130// - RegisterTransientAsset()
131// - CreateAndRegisterAsset()
132// plus the file-scope POLYPHASE_API helpers near the top of this header
133// (FetchAsset, LoadAsset, RegisterImportExtension, GetCurrentAssetDir, …).
135{
136public:
137
139
140 static void Create();
141 static void Destroy();
143
144 void Initialize();
145 void Update(float deltaTime);
146 void DiscoverDirectory(AssetDir* directory, bool engineDir);
147 void RefreshDirectory(AssetDir* directory);
148 void Discover(const char* directoryName, const char* directoryPath);
149 void DiscoverAssetRegistry(const char* registryPath);
150 void DiscoverEmbeddedAssets(struct EmbeddedFile* assets, uint32_t numAssets);
151 void Purge(bool purgeEngineAssets);
152 POLYPHASE_API bool PurgeAsset(const char* name);
153 void RefSweep();
154 void LoadAll();
155
158
159 Asset* ImportEngineAsset(TypeId assetType, AssetDir* dir, const std::string& filename, ImportOptions* options = nullptr);
160 void ImportEngineAssets();
161
162 // Name-based lookup (backward compatible)
163 AssetStub* GetAssetStub(const std::string& name);
164 POLYPHASE_API Asset* GetAsset(const std::string& name);
165 AssetStub* GetSceneAsset(const std::string& name);
166 POLYPHASE_API Asset* LoadAsset(const std::string& name);
167 Asset* LoadAsset(AssetStub& stub);
168 void AsyncLoadAsset(const std::string& name, AssetRef* targetRef);
169
170 // UUID-based lookup (primary)
171 AssetStub* GetAssetStubByUuid(uint64_t uuid);
172 Asset* GetAssetByUuid(uint64_t uuid);
173 Asset* LoadAssetByUuid(uint64_t uuid);
174 void AsyncLoadAssetByUuid(uint64_t uuid, AssetRef* targetRef);
175
176 // Path-based lookup (e.g., "Assets/Models/SM_Plane" or "Models/SM_Plane").
177 // Exported for native addons that resolve assets by authored path.
178 POLYPHASE_API AssetStub* GetAssetStubByPath(const std::string& path);
179 POLYPHASE_API Asset* LoadAssetByPath(const std::string& path);
180 POLYPHASE_API void SaveAsset(const std::string& name);
182 bool UnloadAsset(const std::string& name);
183 bool UnloadAsset(AssetStub& stub);
184
185 bool DoesAssetExist(const std::string& name);
186 bool RenameAsset(Asset* asset, const std::string& newName);
187 std::string GetParentDirectory(const std::string& path);
188 bool RenameDirectory(AssetDir* dir, const std::string& newName);
189 void GatherScriptFilesRecursive(const std::string& dirPath, const std::string& relativePath, std::vector<std::string>& scriptFiles);
190 std::vector<std::string> GetAvailableScriptFiles();
191 std::vector<std::string> GetAvailableFontFiles();
197 void DiscoverAddonPackages(const std::string& packagesDir);
198 std::string GetPolyphaseDirectory();
199 void GatherScriptFiles(const std::string &dir, std::vector<std::string> &outFiles);
200 void GatherFontFiles(const std::string& dir, std::vector<std::string>& outFiles);
202 std::string FindDefaultScenePath();
204 POLYPHASE_API std::unordered_map<std::string, AssetStub*>& GetAssetMap();
205 std::vector<Asset*>& GetTransientAssets();
206 std::vector<AssetStub*> GatherDirtyAssets();
207
208 AssetStub* RegisterAsset(const std::string& filename, TypeId type, AssetDir* directory, EmbeddedFile* embeddedAsset, bool engineAsset, uint64_t uuid = 0);
209 // POLYPHASE_API: exposed to addons so a plugin-registered "Create Asset"
210 // menu entry can drop the .oct directly into the asset browser tree
211 // (RegisterAsset + SaveAsset under the hood) without bouncing through
212 // the import-extension pipeline. Pair with GetCurrentAssetDir() to
213 // land the asset in the user's currently-browsed folder.
214 POLYPHASE_API AssetStub* CreateAndRegisterAsset(TypeId assetType, AssetDir* directory, const std::string& filename, bool engineAsset);
215 POLYPHASE_API AssetDir* GetAssetDirFromPath(const std::string& dirPath);
216
217 bool IsPurging() const;
218
219 // Walks the asset map + transient list looking for a matching pointer
220 // identity without dereferencing the argument. Lets defensive call sites
221 // distinguish "live Asset" from "freed-but-not-yet-nulled raw pointer"
222 // when ASSET_LIVE_REF_TRACKING didn't catch the stale reference
223 // (e.g. across project-switch teardown). Linear scan, only intended for
224 // the rare paths that must defend against a dangling Asset*.
225 bool IsAssetLive(const Asset* asset) const;
226
227protected:
228
229 static ThreadFuncRet AsyncLoadThreadFunc(void* in);
230
232 AssetManager();
233
234 void UpdateEndLoadQueue();
236
237 std::unordered_map<std::string, AssetStub*> mAssetMap; // Name-based lookup (first wins)
238 std::unordered_map<std::string, AssetStub*> mAssetPathMap; // Path-based lookup (e.g., "Models/SM_Plane")
239 std::unordered_map<uint64_t, AssetStub*> mUuidMap; // UUID-based lookup (primary)
240 std::vector<Asset*> mTransientAssets;
242 bool mPurging = false;
243 bool mDestructing = false;
244 std::deque<AsyncLoadRequest*> mBeginLoadQueue;
245 std::deque<AsyncLoadRequest*> mEndLoadQueue;
246 ThreadObject* mAsyncLoadThread = {};
247 MutexObject* mMutex = {};
248
249#if EDITOR
250public:
251 glm::vec4 GetEditorAssetColor(TypeId type);
252 void InitAssetColorMap();
253
254 // Raw (non-.oct) asset packaging registry. Populated during DiscoverDirectory.
255 const std::vector<RawAssetEntry>& GetRawAssetEntries() const { return mRawAssetEntries; }
256
257 // Register a new loose-file entry at runtime (used by
258 // ActionManager::ImportLooseFile so the file ships with the next package
259 // without a full project rescan). Idempotent on mAbsolutePath.
260 void AddRawAssetEntry(const RawAssetEntry& entry);
261
262 // Addon-provided source-extension dispatch (see free-function declarations
263 // above for usage). Stored on the manager so the table survives addon hot-
264 // reload as long as the addon re-registers in its OnLoad.
265 void RegisterImportExtension(const std::string& ext, TypeId type);
266 TypeId LookupImportExtension(const std::string& ext) const;
267
268 // Read the {asset}.meta sidecar at <assetPath>.meta. Returns defaults with
269 // mExists=false when the sidecar is missing or unparseable.
270 static AssetMetaSidecar LoadAssetMeta(const std::string& assetPath);
271
272 // Write the {asset}.meta sidecar. If platformMask == PlatformBit_All AND
273 // embed == false, the sidecar is deleted from disk instead of written so
274 // the source tree stays clean for assets at all-defaults.
275 static void SaveAssetMeta(const std::string& assetPath, uint32_t platformMask, bool embed);
276
277 // Persist new packaging flags to disk via SaveAssetMeta AND update in-memory
278 // AssetStub::mPlatformMask/mEmbed (if assetPath matches a known stub) AND
279 // RawAssetEntry::mPlatformMask/mEmbed (if assetPath matches a raw entry).
280 // Use this from the editor inspector so subsequent packaging sees the new
281 // flags without needing a full rediscover.
282 void ApplyAssetMetaFlags(const std::string& assetPath, uint32_t platformMask, bool embed);
283
284protected:
285 std::unordered_map<TypeId, glm::vec4> mAssetColorMap;
286 std::vector<RawAssetEntry> mRawAssetEntries;
287 std::unordered_map<std::string, TypeId> mImportExtensionMap;
288#endif
289};
290
291template<typename T>
293{
294 T* ret = new T();
296 return ret;
297
298 // Caller still needs to call Create() when ready!
299}
POLYPHASE_API void UnloadAsset(const std::string &name)
Definition AssetManager.cpp:106
POLYPHASE_API void AsyncLoadAsset(const std::string &name, AssetRef *targetRef=nullptr)
Definition AssetManager.cpp:111
POLYPHASE_API AssetStub * FetchAssetStubByUuid(uint64_t uuid)
Definition AssetManager.cpp:137
POLYPHASE_API AssetStub * FetchAssetStub(const std::string &name)
Definition AssetManager.cpp:116
POLYPHASE_API Asset * FetchAsset(const std::string &name)
Definition AssetManager.cpp:96
POLYPHASE_API Asset * LoadAsset(const std::string &name)
Definition AssetManager.cpp:101
T * NewTransientAsset()
Definition AssetManager.h:292
POLYPHASE_API Asset * LoadAssetByUuid(uint64_t uuid)
Definition AssetManager.cpp:127
POLYPHASE_API Asset * FetchAssetByUuid(uint64_t uuid)
Definition AssetManager.cpp:122
POLYPHASE_API void AsyncLoadAssetByUuid(uint64_t uuid, AssetRef *targetRef=nullptr)
Definition AssetManager.cpp:132
#define INVALID_TYPE_ID
Definition Constants.h:40
uint32_t TypeId
Definition EngineTypes.h:72
@ PlatformBit_All
Definition EngineTypes.h:61
bool Update()
Definition Engine.cpp:897
void LogError(const char *format,...)
Definition Log.cpp:289
#define POLYPHASE_API
Definition PolyphaseAPI.h:31
Definition AssetDir.h:11
Definition AssetManager.h:135
bool DoesAssetExist(const std::string &name)
Definition AssetManager.cpp:1771
POLYPHASE_API Asset * LoadAsset(const std::string &name)
Definition AssetManager.cpp:1413
void DiscoverDirectory(AssetDir *directory, bool engineDir)
Definition AssetManager.cpp:513
AssetDir * GetRootDirectory()
Definition AssetManager.cpp:2267
Asset * GetAssetByUuid(uint64_t uuid)
Definition AssetManager.cpp:1473
AssetStub * FindDefaultScene()
Definition AssetManager.cpp:2001
void DiscoverEmbeddedAssets(struct EmbeddedFile *assets, uint32_t numAssets)
Definition AssetManager.cpp:909
void UpdateEndLoadQueue()
Definition AssetManager.cpp:2406
Asset * LoadAssetByUuid(uint64_t uuid)
Definition AssetManager.cpp:1479
POLYPHASE_API AssetDir * GetAssetDirFromPath(const std::string &dirPath)
Definition AssetManager.cpp:432
bool mPurging
Definition AssetManager.h:242
std::vector< std::string > GetAvailableFontFiles()
Definition AssetManager.cpp:2084
static void Create()
Definition AssetManager.cpp:188
void DiscoverAddonPackages(const std::string &packagesDir)
Definition AssetManager.cpp:2230
void AsyncLoadAsset(const std::string &name, AssetRef *targetRef)
Definition AssetManager.cpp:1574
void GatherScriptFiles(const std::string &dir, std::vector< std::string > &outFiles)
Definition AssetManager.cpp:1904
void Initialize()
Definition AssetManager.cpp:235
AssetStub * GetSceneAsset(const std::string &name)
Definition AssetManager.cpp:1400
void GatherFontFiles(const std::string &dir, std::vector< std::string > &outFiles)
Definition AssetManager.cpp:1954
POLYPHASE_API bool PurgeAsset(const char *name)
Definition AssetManager.cpp:1041
static AssetManager * sInstance
Definition AssetManager.h:231
POLYPHASE_API void SaveAsset(const std::string &name)
Definition AssetManager.cpp:1646
static POLYPHASE_API AssetManager * Get()
Definition AssetManager.cpp:203
MutexObject * mMutex
Definition AssetManager.h:247
void Purge(bool purgeEngineAssets)
Definition AssetManager.cpp:990
std::vector< std::string > GetAvailableScriptFiles()
Definition AssetManager.cpp:2104
AssetManager()
Definition AssetManager.cpp:208
AssetStub * RegisterAsset(const std::string &filename, TypeId type, AssetDir *directory, EmbeddedFile *embeddedAsset, bool engineAsset, uint64_t uuid=0)
Definition AssetManager.cpp:268
bool mDestructing
Definition AssetManager.h:243
ThreadObject * mAsyncLoadThread
Definition AssetManager.h:246
bool RenameDirectory(AssetDir *dir, const std::string &newName)
Definition AssetManager.cpp:1868
bool RenameAsset(Asset *asset, const std::string &newName)
Definition AssetManager.cpp:1776
bool IsPurging() const
Definition AssetManager.cpp:488
std::deque< AsyncLoadRequest * > mEndLoadQueue
Definition AssetManager.h:245
std::string GetPolyphaseDirectory()
Definition AssetManager.cpp:2272
POLYPHASE_API AssetStub * GetAssetStubByPath(const std::string &path)
Definition AssetManager.cpp:1534
void AsyncLoadAssetByUuid(uint64_t uuid, AssetRef *targetRef)
Definition AssetManager.cpp:1489
AssetStub * GetAssetStub(const std::string &name)
Definition AssetManager.cpp:1379
std::string GetParentDirectory(const std::string &path)
Definition AssetManager.cpp:1847
std::vector< Asset * > & GetTransientAssets()
Definition AssetManager.cpp:2305
POLYPHASE_API void RegisterTransientAsset(Asset *asset)
Definition AssetManager.cpp:1176
POLYPHASE_API AssetStub * CreateAndRegisterAsset(TypeId assetType, AssetDir *directory, const std::string &filename, bool engineAsset)
Definition AssetManager.cpp:379
std::vector< AssetStub * > GatherDirtyAssets()
Definition AssetManager.cpp:2310
static ThreadFuncRet AsyncLoadThreadFunc(void *in)
Definition AssetManager.cpp:2381
~AssetManager()
Definition AssetManager.cpp:215
void LoadAll()
Definition AssetManager.cpp:1157
void RefreshDirectory(AssetDir *directory)
Definition AssetManager.cpp:667
POLYPHASE_API AssetDir * FindProjectDirectory()
Definition AssetManager.cpp:2182
AssetDir * FindPackagesDirectory()
Definition AssetManager.cpp:2214
std::unordered_map< std::string, AssetStub * > mAssetMap
Definition AssetManager.h:237
AssetStub * GetAssetStubByUuid(uint64_t uuid)
Definition AssetManager.cpp:1465
void UnloadProjectDirectory()
Definition AssetManager.cpp:2280
void DiscoverAssetRegistry(const char *registryPath)
Definition AssetManager.cpp:799
AssetDir * FindEngineDirectory()
Definition AssetManager.cpp:2198
bool ProcessNextBeginLoad()
Definition AssetManager.cpp:2337
std::unordered_map< std::string, AssetStub * > mAssetPathMap
Definition AssetManager.h:238
void GatherScriptFilesRecursive(const std::string &dirPath, const std::string &relativePath, std::vector< std::string > &scriptFiles)
void RefSweep()
Definition AssetManager.cpp:1108
std::deque< AsyncLoadRequest * > mBeginLoadQueue
Definition AssetManager.h:244
bool UnloadAsset(const std::string &name)
Definition AssetManager.cpp:1728
std::vector< Asset * > mTransientAssets
Definition AssetManager.h:240
std::unordered_map< uint64_t, AssetStub * > mUuidMap
Definition AssetManager.h:239
AssetDir * mRootDirectory
Definition AssetManager.h:241
std::string FindDefaultScenePath()
Definition AssetManager.cpp:2014
POLYPHASE_API void UnregisterTransientAsset(Asset *asset)
Definition AssetManager.cpp:1188
static void Destroy()
Definition AssetManager.cpp:194
AssetDir * FindProjectRootDirectory()
POLYPHASE_API std::unordered_map< std::string, AssetStub * > & GetAssetMap()
Definition AssetManager.cpp:2300
void ImportEngineAssets()
Definition AssetManager.cpp:1257
POLYPHASE_API Asset * GetAsset(const std::string &name)
Definition AssetManager.cpp:1387
POLYPHASE_API Asset * LoadAssetByPath(const std::string &path)
Definition AssetManager.cpp:1564
Asset * ImportEngineAsset(TypeId assetType, AssetDir *dir, const std::string &filename, ImportOptions *options=nullptr)
Definition AssetManager.cpp:1202
bool IsAssetLive(const Asset *asset) const
Definition AssetManager.cpp:493
void Discover(const char *directoryName, const char *directoryPath)
Definition AssetManager.cpp:777
Definition AssetRef.h:18
Definition Asset.h:120
Definition Asset.h:109
Definition Material.h:48
virtual bool Is(RuntimeId id) const
Definition Object.h:29
Definition ParticleSystem.h:66
Definition Asset.h:89
Definition AssetManager.h:19
std::string mName
Definition AssetManager.h:20
const EmbeddedFile * mEmbeddedData
Definition AssetManager.h:25
Asset * mAsset
Definition AssetManager.h:27
int32_t mRequeueCount
Definition AssetManager.h:28
TypeId mType
Definition AssetManager.h:26
std::vector< AssetStub * > mDependentAssets
Definition AssetManager.h:24
std::vector< AssetRef * > mTargetRefs
Definition AssetManager.h:23
uint64_t mUuid
Definition AssetManager.h:22
std::string mPath
Definition AssetManager.h:21
Definition EmbeddedFile.h:6