assetManager.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _ASSET_MANAGER_H_
  23. #define _ASSET_MANAGER_H_
  24. #ifndef _SIMBASE_H_
  25. #include "console/sim.h"
  26. #endif
  27. #ifndef _TAML_H_
  28. #include "persistence/taml/taml.h"
  29. #endif
  30. #ifndef _MODULE_DEFINITION_H
  31. #include "module/moduleDefinition.h"
  32. #endif
  33. #ifndef _MODULE_CALLBACKS_H_
  34. #include "module/moduleCallbacks.h"
  35. #endif
  36. #ifndef _ASSET_BASE_H_
  37. #include "assets/assetBase.h"
  38. #endif
  39. #ifndef _ASSET_DEFINITION_H_
  40. #include "assets/assetDefinition.h"
  41. #endif
  42. #ifndef _ASSET_TAGS_MANIFEST_H_
  43. #include "assets/assetTagsManifest.h"
  44. #endif
  45. #ifndef _ASSET_QUERY_H_
  46. #include "assets/assetQuery.h"
  47. #endif
  48. #ifndef _ASSET_FIELD_TYPES_H_
  49. #include "assets/assetFieldTypes.h"
  50. #endif
  51. // Debug Profiling.
  52. #include "platform/profiler.h"
  53. //-----------------------------------------------------------------------------
  54. class AssetPtrCallback;
  55. class AssetPtrBase;
  56. //-----------------------------------------------------------------------------
  57. class AssetManager : public SimObject, public ModuleCallbacks
  58. {
  59. private:
  60. typedef SimObject Parent;
  61. typedef StringTableEntry typeAssetId;
  62. typedef StringTableEntry typeAssetName;
  63. typedef StringTableEntry typeReferenceFilePath;
  64. typedef HashMap<typeAssetId, AssetDefinition*> typeDeclaredAssetsHash;
  65. typedef HashTable<typeAssetId, typeReferenceFilePath> typeReferencedAssetsHash;
  66. typedef HashTable<typeAssetId, typeAssetId> typeAssetDependsOnHash;
  67. typedef HashTable<typeAssetId, typeAssetId> typeAssetIsDependedOnHash;
  68. typedef HashMap<AssetPtrBase*, AssetPtrCallback*> typeAssetPtrRefreshHash;
  69. /// Declared assets.
  70. typeDeclaredAssetsHash mDeclaredAssets;
  71. /// Referenced assets.
  72. typeReferencedAssetsHash mReferencedAssets;
  73. /// Asset dependencies.
  74. typeAssetDependsOnHash mAssetDependsOn;
  75. typeAssetIsDependedOnHash mAssetIsDependedOn;
  76. /// Asset tags.
  77. SimObjectPtr<AssetTagsManifest> mAssetTagsManifest;
  78. SimObjectPtr<ModuleDefinition> mAssetTagsModuleDefinition;
  79. /// Asset pointer refresh notifications.
  80. typeAssetPtrRefreshHash mAssetPtrRefreshNotifications;
  81. /// Miscellaneous.
  82. bool mEchoInfo;
  83. bool mIgnoreAutoUnload;
  84. U32 mLoadedInternalAssetsCount;
  85. U32 mLoadedExternalAssetsCount;
  86. U32 mLoadedPrivateAssetsCount;
  87. U32 mAcquiredReferenceCount;
  88. U32 mMaxLoadedInternalAssetsCount;
  89. U32 mMaxLoadedExternalAssetsCount;
  90. U32 mMaxLoadedPrivateAssetsCount;
  91. Taml mTaml;
  92. public:
  93. AssetManager();
  94. virtual ~AssetManager() {}
  95. /// SimObject overrides
  96. virtual bool onAdd();
  97. virtual void onRemove();
  98. static void initPersistFields();
  99. /// Declared assets.
  100. bool addModuleDeclaredAssets( ModuleDefinition* pModuleDefinition );
  101. bool addDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath );
  102. StringTableEntry addPrivateAsset( AssetBase* pAssetBase );
  103. bool removeDeclaredAssets( ModuleDefinition* pModuleDefinition );
  104. bool removeDeclaredAsset( const char* pAssetId );
  105. bool renameDeclaredAsset( const char* pAssetIdFrom, const char* pAssetIdTo );
  106. StringTableEntry getAssetName( const char* pAssetId );
  107. StringTableEntry getAssetDescription( const char* pAssetId );
  108. StringTableEntry getAssetCategory( const char* pAssetId );
  109. StringTableEntry getAssetType( const char* pAssetId );
  110. StringTableEntry getAssetFilePath( const char* pAssetId );
  111. StringTableEntry getAssetPath( const char* pAssetId );
  112. ModuleDefinition* getAssetModuleDefinition( const char* pAssetId );
  113. bool isAssetInternal( const char* pAssetId );
  114. bool isAssetPrivate( const char* pAssetId );
  115. bool isAssetAutoUnload( const char* pAssetId );
  116. bool isAssetLoaded( const char* pAssetId );
  117. bool isDeclaredAsset( const char* pAssetId );
  118. bool doesAssetDependOn( const char* pAssetId, const char* pDependsOnAssetId );
  119. bool isAssetDependedOn( const char* pAssetId, const char* pDependedOnByAssetId );
  120. /// Referenced assets.
  121. bool compileReferencedAssets( ModuleDefinition* pModuleDefinition );
  122. bool isReferencedAsset( const char* pAssetId );
  123. bool renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo );
  124. /// Public asset acquisition.
  125. template<typename T> T* acquireAsset( const char* pAssetId )
  126. {
  127. // Sanity!
  128. AssertFatal( pAssetId != NULL, "Cannot acquire NULL asset Id." );
  129. // Is this an empty asset Id?
  130. if ( *pAssetId == 0 )
  131. {
  132. // Yes, so return nothing.
  133. return NULL;
  134. }
  135. // Find asset.
  136. AssetDefinition* pAssetDefinition = findAsset( pAssetId );
  137. // Did we find the asset?
  138. if ( pAssetDefinition == NULL )
  139. {
  140. // No, so warn.
  141. Con::warnf( "Asset Manager: Failed to acquire asset Id '%s' as it does not exist.", pAssetId );
  142. return NULL;
  143. }
  144. // Is asset loading?
  145. if ( pAssetDefinition->mAssetLoading == true )
  146. {
  147. // Yes, so we've got a circular loop which we cannot resolve!
  148. Con::warnf( "Asset Manager: Failed to acquire asset Id '%s' as loading it involves a cyclic dependency on itself which cannot be resolved.", pAssetId );
  149. return NULL;
  150. }
  151. // Info.
  152. if ( mEchoInfo )
  153. {
  154. Con::printSeparator();
  155. Con::printf( "Asset Manager: Started acquiring Asset Id '%s'...", pAssetId );
  156. }
  157. // Is the asset already loaded?
  158. if ( pAssetDefinition->mpAssetBase == NULL )
  159. {
  160. // No, so info
  161. if ( mEchoInfo )
  162. {
  163. // Fetch asset Id.
  164. StringTableEntry assetId = StringTable->insert( pAssetId );
  165. // Find any asset dependencies.
  166. typeAssetDependsOnHash::Iterator assetDependenciesItr = mAssetDependsOn.find( assetId );
  167. // Does the asset have any dependencies?
  168. if ( assetDependenciesItr != mAssetDependsOn.end() )
  169. {
  170. // Yes, so show all dependency assets.
  171. Con::printf( "Asset Manager: > Found dependencies:" );
  172. // Iterate all dependencies.
  173. while( assetDependenciesItr != mAssetDependsOn.end() && assetDependenciesItr->key == assetId )
  174. {
  175. // Info.
  176. Con::printf( "Asset Manager: > Asset Id '%s'", assetDependenciesItr->value );
  177. // Next dependency.
  178. assetDependenciesItr++;
  179. }
  180. }
  181. }
  182. // Flag asset as loading.
  183. pAssetDefinition->mAssetLoading = true;
  184. // Generate primary asset.
  185. pAssetDefinition->mpAssetBase = mTaml.read<T>( pAssetDefinition->mAssetBaseFilePath );
  186. // Flag asset as finished loading.
  187. pAssetDefinition->mAssetLoading = false;
  188. // Did we generate the asset?
  189. if ( pAssetDefinition->mpAssetBase == NULL )
  190. {
  191. // No, so warn.
  192. Con::warnf( "Asset Manager: > Failed to acquire asset Id '%s' as loading the asset file failed to return the asset or the correct asset type: '%s'.",
  193. pAssetId, pAssetDefinition->mAssetBaseFilePath );
  194. return NULL;
  195. }
  196. // Increase loaded count.
  197. pAssetDefinition->mAssetLoadedCount++;
  198. // Info.
  199. if ( mEchoInfo )
  200. {
  201. Con::printf( "Asset Manager: > Loading asset into memory as object Id '%d' from file '%s'.",
  202. pAssetDefinition->mpAssetBase->getId(), pAssetDefinition->mAssetBaseFilePath );
  203. }
  204. // Set ownership by asset manager.
  205. pAssetDefinition->mpAssetBase->setOwned( this, pAssetDefinition );
  206. // Is the asset internal?
  207. if ( pAssetDefinition->mAssetInternal )
  208. {
  209. // Yes, so increase internal loaded asset count.
  210. if ( ++mLoadedInternalAssetsCount > mMaxLoadedInternalAssetsCount )
  211. mMaxLoadedInternalAssetsCount = mLoadedInternalAssetsCount;
  212. }
  213. else
  214. {
  215. // No, so increase external loaded assets count.
  216. if ( ++mLoadedExternalAssetsCount > mMaxLoadedExternalAssetsCount )
  217. mMaxLoadedExternalAssetsCount = mLoadedExternalAssetsCount;
  218. }
  219. }
  220. else if ( pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() == 0 )
  221. {
  222. // Info.
  223. if ( mEchoInfo )
  224. {
  225. Con::printf( "Asset Manager: > Acquiring from idle state." );
  226. }
  227. }
  228. // Set acquired asset.
  229. T* pAcquiredAsset = dynamic_cast<T*>( (AssetBase*)pAssetDefinition->mpAssetBase );
  230. // Is asset the correct type?
  231. if ( pAcquiredAsset == NULL )
  232. {
  233. // No, so warn.
  234. Con::warnf( "Asset Manager: > Failed to acquire asset Id '%s' as it was not the required asset type: '%s'.", pAssetId, pAssetDefinition->mAssetBaseFilePath );
  235. return NULL;
  236. }
  237. // Acquire asset reference.
  238. pAcquiredAsset->acquireAssetReference();
  239. // Info.
  240. if ( mEchoInfo )
  241. {
  242. Con::printf( "Asset Manager: > Finished acquiring asset. Reference count now '%d'.", pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() );
  243. Con::printSeparator();
  244. }
  245. return pAcquiredAsset;
  246. }
  247. /// Private asset acquisition.
  248. template<typename T> T* acquireAsPrivateAsset( const char* pAssetId )
  249. {
  250. // Acquire the asset normally.
  251. T* pAsset = acquireAsset<T>( pAssetId );
  252. // Finish if the asset was not acquired.
  253. if ( pAsset == NULL )
  254. return NULL;
  255. // Clone the asset.
  256. T* pAssetClone = dynamic_cast<T*>( pAsset->clone() );
  257. // Sanity!
  258. AssertFatal( pAssetClone != NULL, "acquireAsPrivateAsset() - Failed to clone asset type." );
  259. // Release the public asset.
  260. releaseAsset( pAssetId );
  261. // Add as a private asset.
  262. addPrivateAsset( pAssetClone );
  263. return pAssetClone;
  264. }
  265. bool releaseAsset( const char* pAssetId );
  266. void purgeAssets( void );
  267. /// Asset deletion.
  268. bool deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies );
  269. // Asset refresh notification.
  270. bool refreshAsset( const char* pAssetId );
  271. void refreshAllAssets( const bool includeUnloaded = false );
  272. void registerAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase, AssetPtrCallback* pCallback );
  273. void unregisterAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase );
  274. /// Asset tags.
  275. bool loadAssetTags( ModuleDefinition* pModuleDefinition );
  276. bool saveAssetTags( void );
  277. bool restoreAssetTags( void );
  278. inline AssetTagsManifest* getAssetTags( void ) const { return mAssetTagsManifest; }
  279. /// Info.
  280. inline U32 getDeclaredAssetCount( void ) const { return (U32)mDeclaredAssets.size(); }
  281. inline U32 getReferencedAssetCount( void ) const { return (U32)mReferencedAssets.size(); }
  282. inline U32 getLoadedInternalAssetCount( void ) const { return mLoadedInternalAssetsCount; }
  283. inline U32 getLoadedExternalAssetCount( void ) const { return mLoadedExternalAssetsCount; }
  284. inline U32 getLoadedPrivateAssetCount( void ) const { return mLoadedPrivateAssetsCount; }
  285. inline U32 getMaxLoadedInternalAssetCount( void ) const { return mMaxLoadedInternalAssetsCount; }
  286. inline U32 getMaxLoadedExternalAssetCount( void ) const { return mMaxLoadedExternalAssetsCount; }
  287. inline U32 getMaxLoadedPrivateAssetCount( void ) const { return mMaxLoadedPrivateAssetsCount; }
  288. void dumpDeclaredAssets( void ) const;
  289. /// Total acquired asset references.
  290. inline void acquireAcquiredReferenceCount( void ) { mAcquiredReferenceCount++; }
  291. inline void releaseAcquiredReferenceCount( void ) { AssertFatal( mAcquiredReferenceCount != 0, "AssetManager: Invalid acquired reference count." ); mAcquiredReferenceCount--; }
  292. inline U32 getAcquiredReferenceCount( void ) const { return mAcquiredReferenceCount; }
  293. /// Asset queries.
  294. S32 findAllAssets( AssetQuery* pAssetQuery, const bool ignoreInternal = true, const bool ignorePrivate = true );
  295. S32 findAssetName( AssetQuery* pAssetQuery, const char* pAssetName, const bool partialName = false );
  296. S32 findAssetCategory( AssetQuery* pAssetQuery, const char* pAssetCategory, const bool assetQueryAsSource = false );
  297. S32 findAssetAutoUnload( AssetQuery* pAssetQuery, const bool assetAutoUnload, const bool assetQueryAsSource = false );
  298. S32 findAssetInternal( AssetQuery* pAssetQuery, const bool assetInternal, const bool assetQueryAsSource = false );
  299. S32 findAssetPrivate( AssetQuery* pAssetQuery, const bool assetPrivate, const bool assetQueryAsSource = false );
  300. S32 findAssetType( AssetQuery* pAssetQuery, const char* pAssetType, const bool assetQueryAsSource = false );
  301. S32 findAssetDependsOn( AssetQuery* pAssetQuery, const char* pAssetId );
  302. S32 findAssetIsDependedOn( AssetQuery* pAssetQuery, const char* pAssetId );
  303. S32 findInvalidAssetReferences( AssetQuery* pAssetQuery );
  304. S32 findTaggedAssets( AssetQuery* pAssetQuery, const char* pAssetTagNames, const bool assetQueryAsSource = false );
  305. S32 findAssetLooseFile( AssetQuery* pAssetQuery, const char* pLooseFile, const bool assetQueryAsSource = false );
  306. /// Declare Console Object.
  307. DECLARE_CONOBJECT( AssetManager );
  308. private:
  309. bool scanDeclaredAssets( const char* pPath, const char* pExtension, const bool recurse, ModuleDefinition* pModuleDefinition );
  310. bool scanReferencedAssets( const char* pPath, const char* pExtension, const bool recurse );
  311. AssetDefinition* findAsset( const char* pAssetId );
  312. void addReferencedAsset( StringTableEntry assetId, StringTableEntry referenceFilePath );
  313. void renameAssetReferences( StringTableEntry assetIdFrom, StringTableEntry assetIdTo );
  314. void removeAssetReferences( StringTableEntry assetId );
  315. void renameAssetDependencies( StringTableEntry assetIdFrom, StringTableEntry assetIdTo );
  316. void removeAssetDependencies( const char* pAssetId );
  317. void removeAssetLooseFiles( const char* pAssetId );
  318. void unloadAsset( AssetDefinition* pAssetDefinition );
  319. /// Module callbacks.
  320. virtual void onModulePreLoad( ModuleDefinition* pModuleDefinition );
  321. virtual void onModulePreUnload( ModuleDefinition* pModuleDefinition );
  322. virtual void onModulePostUnload( ModuleDefinition* pModuleDefinition );
  323. };
  324. //-----------------------------------------------------------------------------
  325. extern AssetManager AssetDatabase;
  326. #endif // _ASSET_MANAGER_H_