@@ -203,28 +203,37 @@ class IAssetManager : public core::IReferenceCounted, public core::QuitSignallin
203
203
*/
204
204
SAssetBundle getAssetInHierarchy (io::IReadFile* _file, const std::string& _supposedFilename, const IAssetLoader::SAssetLoadParams& _params, uint32_t _hierarchyLevel, IAssetLoader::IAssetLoaderOverride* _override)
205
205
{
206
+ const uint32_t restoreLevels = (_hierarchyLevel >= _params.restoreLevels ) ? 0u : (_params.restoreLevels - _hierarchyLevel);
207
+
206
208
IAssetLoader::SAssetLoadParams params (_params);
207
209
if (params.meshManipulatorOverride == nullptr )
208
210
{
209
211
params.meshManipulatorOverride = m_meshManipulator.get ();
210
212
}
213
+ if (restoreLevels)
214
+ {
215
+ using flags_t = std::underlying_type_t <IAssetLoader::E_CACHING_FLAGS>;
216
+ flags_t mask = ~static_cast <flags_t >(0 );
217
+ mask = core::bitfieldInsert<flags_t >(mask, IAssetLoader::ECF_DONT_CACHE_REFERENCES, 2u *_hierarchyLevel, 2u *restoreLevels);
218
+ params.cacheFlags = static_cast <IAssetLoader::E_CACHING_FLAGS>(params.cacheFlags & mask);
219
+ }
211
220
212
221
IAssetLoader::SAssetLoadContext ctx{params, _file};
213
222
214
223
std::string filename = _file ? _file->getFileName ().c_str () : _supposedFilename;
215
- io::IReadFile* file = _override->getLoadFile (_file, filename, ctx, _hierarchyLevel);
224
+ io::IReadFile* file = _override->getLoadFile (_file, filename, ctx, _hierarchyLevel); // WARNING: mem-leak possibility: _override should return smart_ptr<IReadFile> (TODO, inspect this)
216
225
filename = file ? file->getFileName ().c_str () : _supposedFilename;
217
226
218
227
const uint64_t levelFlags = params.cacheFlags >> ((uint64_t )_hierarchyLevel * 2ull );
219
228
220
- SAssetBundle asset ;
229
+ SAssetBundle bundle ;
221
230
if ((levelFlags & IAssetLoader::ECF_DUPLICATE_TOP_LEVEL) != IAssetLoader::ECF_DUPLICATE_TOP_LEVEL)
222
231
{
223
232
auto found = findAssets (filename);
224
233
if (found->size ())
225
234
return _override->chooseRelevantFromFound (found->begin (), found->end (), ctx, _hierarchyLevel);
226
- else if (!(asset = _override->handleSearchFail (filename, ctx, _hierarchyLevel)).getContents ().empty ())
227
- return asset ;
235
+ else if (!(bundle = _override->handleSearchFail (filename, ctx, _hierarchyLevel)).getContents ().empty ())
236
+ return bundle ;
228
237
}
229
238
230
239
// if at this point, and after looking for an asset in cache, file is still nullptr, then return nullptr
@@ -235,30 +244,61 @@ class IAssetManager : public core::IReferenceCounted, public core::QuitSignallin
235
244
// loaders associated with the file's extension tryout
236
245
for (auto & loader : capableLoadersRng)
237
246
{
238
- if (loader.second ->isALoadableFileFormat (file) && !(asset = loader.second ->loadAsset (file, params, _override, _hierarchyLevel)).getContents ().empty ())
247
+ if (loader.second ->isALoadableFileFormat (file) && !(bundle = loader.second ->loadAsset (file, params, _override, _hierarchyLevel)).getContents ().empty ())
239
248
break ;
240
249
}
241
- for (auto loaderItr = std::begin (m_loaders.vector ); asset .getContents ().empty () && loaderItr != std::end (m_loaders.vector ); ++loaderItr) // all loaders tryout
250
+ for (auto loaderItr = std::begin (m_loaders.vector ); bundle .getContents ().empty () && loaderItr != std::end (m_loaders.vector ); ++loaderItr) // all loaders tryout
242
251
{
243
- if ((*loaderItr)->isALoadableFileFormat (file) && !(asset = (*loaderItr)->loadAsset (file, params, _override, _hierarchyLevel)).getContents ().empty ())
252
+ if ((*loaderItr)->isALoadableFileFormat (file) && !(bundle = (*loaderItr)->loadAsset (file, params, _override, _hierarchyLevel)).getContents ().empty ())
244
253
break ;
245
254
}
246
255
247
- if (!asset .getContents ().empty () &&
256
+ if (!bundle .getContents ().empty () &&
248
257
((levelFlags & IAssetLoader::ECF_DONT_CACHE_TOP_LEVEL) != IAssetLoader::ECF_DONT_CACHE_TOP_LEVEL) &&
249
258
((levelFlags & IAssetLoader::ECF_DUPLICATE_TOP_LEVEL) != IAssetLoader::ECF_DUPLICATE_TOP_LEVEL))
250
259
{
251
- _override->insertAssetIntoCache (asset , filename, ctx, _hierarchyLevel);
260
+ _override->insertAssetIntoCache (bundle , filename, ctx, _hierarchyLevel);
252
261
}
253
- else if (asset .getContents ().empty ())
262
+ else if (bundle .getContents ().empty ())
254
263
{
255
264
bool addToCache;
256
- asset = _override->handleLoadFail (addToCache, file, filename, filename, ctx, _hierarchyLevel);
257
- if (!asset.getContents ().empty () && addToCache)
258
- _override->insertAssetIntoCache (asset, filename, ctx, _hierarchyLevel);
265
+ bundle = _override->handleLoadFail (addToCache, file, filename, filename, ctx, _hierarchyLevel);
266
+ if (!bundle.getContents ().empty () && addToCache)
267
+ _override->insertAssetIntoCache (bundle, filename, ctx, _hierarchyLevel);
268
+ }
269
+
270
+ if (bundle.getContents ().empty () /* || none of req levels is dummy*/ )
271
+ return bundle;
272
+
273
+ if (restoreLevels)
274
+ {
275
+ auto reloadParams = _params;
276
+ {
277
+ using flags_t = std::underlying_type_t <IAssetLoader::E_CACHING_FLAGS>;
278
+ constexpr uint32_t bitdepth = sizeof (flags_t )*8u ;
279
+ const flags_t zeroOutMask = (~static_cast <flags_t >(0 )) >> (bitdepth - 2u *(restoreLevels + _hierarchyLevel));
280
+ flags_t reloadFlags = reloadParams.cacheFlags ;
281
+ reloadFlags &= zeroOutMask; // make sure we never pointlessy reload levels above (_restoreLevels+_hierLevel) in reload pass
282
+ // set flags for levels [_hierLevel,_hierLevel+_restoreLevels) to dont look into cache and dont put into cache
283
+ reloadFlags = core::bitfieldInsert<flags_t >(reloadFlags, IAssetLoader::ECF_DUPLICATE_REFERENCES, _hierarchyLevel*2u , restoreLevels*2u );
284
+ reloadParams.cacheFlags = static_cast <IAssetLoader::E_CACHING_FLAGS>(reloadFlags);
285
+
286
+ reloadParams.restoreLevels = 0u ; // make sure it wont turn into infinite recursion
287
+ reloadParams.reload = true ; // TODO (consider): alternative to this flag: another method in override just to let user choose asset for restore
288
+ }
289
+ IAssetLoader::SAssetLoadContext ctx (params, file);
290
+ auto asset = _override->chooseDefaultAsset (bundle, ctx);
291
+ if (!asset->isAnyDependencyDummy (restoreLevels - 1u ))
292
+ return bundle;
293
+
294
+ auto reloadBundle = getAssetInHierarchy (_file, _supposedFilename, reloadParams, _hierarchyLevel, _override);
295
+
296
+ bool restoreSucceeded = _override->handleRestore (std::move (asset), bundle, reloadBundle, restoreLevels);
297
+ if (!restoreSucceeded) // hm? return empty bundle if restore was requested, but did not succeeded? or just return the bundle? (TODO consider)
298
+ return {};
259
299
}
260
300
261
- return asset ;
301
+ return bundle ;
262
302
}
263
303
// TODO change name
264
304
SAssetBundle getAssetInHierarchy (const std::string& _filePath, const IAssetLoader::SAssetLoadParams& _params, uint32_t _hierarchyLevel, IAssetLoader::IAssetLoaderOverride* _override)
0 commit comments