assetManager.cpp
Engine/source/assets/assetManager.cpp
Public Variables
Public Functions
Detailed Description
Public Variables
AssetManager AssetDatabase
Public Functions
descendingAssetDefinitionLoadCount(const void * a, const void * b)
IMPLEMENT_CONOBJECT(AssetManager )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2013 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "assetManager.h" 25 26#ifndef _ASSET_PTR_H_ 27#include "assetPtr.h" 28#endif 29 30#ifndef _REFERENCED_ASSETS_H_ 31#include "assets/referencedAssets.h" 32#endif 33 34#ifndef _DECLARED_ASSETS_H_ 35#include "assets/declaredAssets.h" 36#endif 37 38#ifndef _TAML_ASSET_REFERENCED_VISITOR_H_ 39#include "tamlAssetReferencedVisitor.h" 40#endif 41 42#ifndef _TAML_ASSET_DECLARED_VISITOR_H_ 43#include "tamlAssetDeclaredVisitor.h" 44#endif 45 46#ifndef _TAML_ASSET_DECLARED_UPDATE_VISITOR_H_ 47#include "tamlAssetDeclaredUpdateVisitor.h" 48#endif 49 50#ifndef _TAML_ASSET_REFERENCED_UPDATE_VISITOR_H_ 51#include "tamlAssetReferencedUpdateVisitor.h" 52#endif 53 54#ifndef _CONSOLETYPES_H_ 55#include "console/consoleTypes.h" 56#endif 57 58// Script bindings. 59#include "assetManager_ScriptBinding.h" 60 61//----------------------------------------------------------------------------- 62 63IMPLEMENT_CONOBJECT( AssetManager ); 64 65//----------------------------------------------------------------------------- 66 67AssetManager AssetDatabase; 68 69//----------------------------------------------------------------------------- 70 71AssetManager::AssetManager() : 72 mLoadedInternalAssetsCount( 0 ), 73 mLoadedExternalAssetsCount( 0 ), 74 mLoadedPrivateAssetsCount( 0 ), 75 mMaxLoadedInternalAssetsCount( 0 ), 76 mMaxLoadedExternalAssetsCount( 0 ), 77 mMaxLoadedPrivateAssetsCount( 0 ), 78 mAcquiredReferenceCount( 0 ), 79 mEchoInfo( false ), 80 mIgnoreAutoUnload( true ) 81{ 82} 83 84//----------------------------------------------------------------------------- 85 86bool AssetManager::onAdd() 87{ 88 // Call parent. 89 if ( !Parent::onAdd() ) 90 return false; 91 92 return true; 93} 94 95//----------------------------------------------------------------------------- 96 97void AssetManager::onRemove() 98{ 99 // Do we have an asset tags manifest? 100 if ( !mAssetTagsManifest.isNull() ) 101 { 102 // Yes, so remove it. 103 mAssetTagsManifest->deleteObject(); 104 } 105 106 // Call parent. 107 Parent::onRemove(); 108} 109 110//----------------------------------------------------------------------------- 111 112void AssetManager::initPersistFields() 113{ 114 // Call parent. 115 Parent::initPersistFields(); 116 117 addField( "EchoInfo", TypeBool, Offset(mEchoInfo, AssetManager), "Whether the asset manager echos extra information to the console or not." ); 118 addField( "IgnoreAutoUnload", TypeBool, Offset(mIgnoreAutoUnload, AssetManager), "Whether the asset manager should ignore unloading of auto-unload assets or not." ); 119} 120 121//----------------------------------------------------------------------------- 122 123bool AssetManager::compileReferencedAssets( ModuleDefinition* pModuleDefinition ) 124{ 125 // Debug Profiling. 126 PROFILE_SCOPE(AssetManager_CompileReferencedAsset); 127 128 // Sanity! 129 AssertFatal( pModuleDefinition != NULL, "Cannot add declared assets using a NULL module definition" ); 130 131 // Clear referenced assets. 132 mReferencedAssets.clear(); 133 134 // Iterate the module definition children. 135 for( SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr ) 136 { 137 // Fetch the referenced assets. 138 ReferencedAssets* pReferencedAssets = dynamic_cast<ReferencedAssets*>( *itr ); 139 140 // Skip if it's not a referenced assets location. 141 if ( pReferencedAssets == NULL ) 142 continue; 143 144 // Expand asset manifest location. 145 char filePathBuffer[1024]; 146 dSprintf( filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pReferencedAssets->getPath() ); 147 148 // Scan referenced assets at location. 149 if ( !scanReferencedAssets( filePathBuffer, pReferencedAssets->getExtension(), pReferencedAssets->getRecurse() ) ) 150 { 151 // Warn. 152 Con::warnf( "AssetManager::compileReferencedAssets() - Could not scan for referenced assets at location '%s' with extension '%s'.", filePathBuffer, pReferencedAssets->getExtension() ); 153 } 154 } 155 156 return true; 157} 158 159//----------------------------------------------------------------------------- 160 161bool AssetManager::addModuleDeclaredAssets( ModuleDefinition* pModuleDefinition ) 162{ 163 // Debug Profiling. 164 PROFILE_SCOPE(AssetManager_AddDeclaredAssets); 165 166 // Sanity! 167 AssertFatal( pModuleDefinition != NULL, "Cannot add declared assets using a NULL module definition" ); 168 169 // Does the module have any assets associated with it? 170 if ( pModuleDefinition->getModuleAssets().size() > 0 ) 171 { 172 // Yes, so warn. 173 Con::warnf( "Asset Manager: Cannot add declared assets to module '%s' as it already has existing assets.", pModuleDefinition->getSignature() ); 174 return false; 175 } 176 177 // Iterate the module definition children. 178 for( SimSet::iterator itr = pModuleDefinition->begin(); itr != pModuleDefinition->end(); ++itr ) 179 { 180 // Fetch the declared assets. 181 DeclaredAssets* pDeclaredAssets = dynamic_cast<DeclaredAssets*>( *itr ); 182 183 // Skip if it's not a declared assets location. 184 if ( pDeclaredAssets == NULL ) 185 continue; 186 187 // Expand asset manifest location. 188 char filePathBuffer[1024]; 189 String mdldfpth = pModuleDefinition->getModulePath(); 190 String astfpth = pDeclaredAssets->getPath(); 191 192 //dSprintf( filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pDeclaredAssets->getPath() ); 193 dSprintf(filePathBuffer, sizeof(filePathBuffer), "%s/%s", pModuleDefinition->getModulePath(), pDeclaredAssets->getPath()); 194 195 // Scan declared assets at location. 196 if ( !scanDeclaredAssets( filePathBuffer, pDeclaredAssets->getExtension(), pDeclaredAssets->getRecurse(), pModuleDefinition ) ) 197 { 198 // Warn. 199 Con::warnf( "AssetManager::addModuleDeclaredAssets() - Could not scan for declared assets at location '%s' with extension '%s'.", filePathBuffer, pDeclaredAssets->getExtension() ); 200 } 201 } 202 203 return true; 204} 205 206//----------------------------------------------------------------------------- 207 208bool AssetManager::addDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath ) 209{ 210 // Debug Profiling. 211 PROFILE_SCOPE(AssetManager_AddSingleDeclaredAsset); 212 213 // Sanity! 214 AssertFatal( pModuleDefinition != NULL, "Cannot add single declared asset using a NULL module definition" ); 215 AssertFatal( pAssetFilePath != NULL, "Cannot add single declared asset using a NULL asset file-path." ); 216 217 // Expand asset file-path. 218 char assetFilePathBuffer[1024]; 219 Con::expandPath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetFilePath ); 220 221 // Find the final slash which should be just before the file. 222 char* pFileStart = dStrrchr( assetFilePathBuffer, '/' ); 223 224 // Did we find the final slash? 225 if ( pFileStart == NULL ) 226 { 227 // No, so warn. 228 Con::warnf( "AssetManager::addDeclaredAsset() - Could not add single declared asset file '%s' as file-path '%s' is not valid.", 229 assetFilePathBuffer, 230 pModuleDefinition->getModulePath() ); 231 return false; 232 } 233 234 // Terminate path at slash. 235 *pFileStart = 0; 236 237 // Move to next character which should be the file start. 238 pFileStart++; 239 240 // Scan declared assets at location. 241 if ( !scanDeclaredAssets( assetFilePathBuffer, pFileStart, false, pModuleDefinition ) ) 242 { 243 // Warn. 244 Con::warnf( "AssetManager::addDeclaredAsset() - Could not scan declared assets at location '%s' with extension '%s'.", assetFilePathBuffer, pFileStart ); 245 return false; 246 } 247 248 return true; 249} 250 251//----------------------------------------------------------------------------- 252 253StringTableEntry AssetManager::addPrivateAsset( AssetBase* pAssetBase ) 254{ 255 // Debug Profiling. 256 PROFILE_SCOPE(AssetManager_AddPrivateAsset); 257 258 // Sanity! 259 AssertFatal( pAssetBase != NULL, "Cannot add a NULL private asset." ); 260 261 // Is the asset already added? 262 if (pAssetBase->mpAssetDefinition->mAssetId != StringTable->EmptyString()) 263 { 264 // Yes, so warn. 265 Con::warnf( "Cannot add private asset '%d' as it has already been assigned.", pAssetBase->mpAssetDefinition->mAssetId ); 266 return StringTable->EmptyString(); 267 } 268 269 static U32 masterPrivateAssetId = 1; 270 271 // Create asset definition. 272 AssetDefinition* pAssetDefinition = new AssetDefinition(); 273 274 // Fetch source asset definition. 275 AssetDefinition* pSourceAssetDefinition = pAssetBase->mpAssetDefinition; 276 277 // Configure asset. 278 pAssetDefinition->mpAssetBase = pAssetBase; 279 pAssetDefinition->mAssetDescription = pSourceAssetDefinition->mAssetDescription; 280 pAssetDefinition->mAssetCategory = pSourceAssetDefinition->mAssetCategory; 281 pAssetDefinition->mAssetAutoUnload = true; 282 pAssetDefinition->mAssetRefreshEnable = false; 283 pAssetDefinition->mAssetType = StringTable->insert( pAssetBase->getClassName() ); 284 pAssetDefinition->mAssetLoadedCount = 0; 285 pAssetDefinition->mAssetInternal = false; 286 pAssetDefinition->mAssetPrivate = true; 287 288 // Format asset name. 289 char assetNameBuffer[256]; 290 dSprintf(assetNameBuffer, sizeof(assetNameBuffer), "%s_%d", pAssetDefinition->mAssetType, masterPrivateAssetId++ ); 291 292 // Set asset identity. 293 pAssetDefinition->mAssetName = StringTable->insert( assetNameBuffer ); 294 pAssetDefinition->mAssetId = pAssetDefinition->mAssetName; 295 296 // Ensure that the source asset is fully synchronized with the new asset definition. 297 pSourceAssetDefinition->mAssetName = pAssetDefinition->mAssetName; 298 pSourceAssetDefinition->mAssetAutoUnload = pAssetDefinition->mAssetAutoUnload; 299 pSourceAssetDefinition->mAssetInternal = pAssetDefinition->mAssetInternal; 300 301 // Set ownership by asset manager. 302 pAssetDefinition->mpAssetBase->setOwned( this, pAssetDefinition ); 303 304 // Store in declared assets. 305 mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition ); 306 307 // Increase the private loaded asset count. 308 if ( ++mLoadedPrivateAssetsCount > mMaxLoadedPrivateAssetsCount ) 309 mMaxLoadedPrivateAssetsCount = mLoadedPrivateAssetsCount; 310 311 return pAssetDefinition->mAssetId; 312} 313 314//----------------------------------------------------------------------------- 315 316bool AssetManager::removeDeclaredAssets( ModuleDefinition* pModuleDefinition ) 317{ 318 // Debug Profiling. 319 PROFILE_SCOPE(AssetManager_RemoveDeclaredAssets); 320 321 // Sanity! 322 AssertFatal( pModuleDefinition != NULL, "Cannot remove declared assets using a NULL module definition" ); 323 324 // Fetch module assets. 325 ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets(); 326 327 // Remove all module assets. 328 while ( moduleAssets.size() > 0 ) 329 { 330 // Fetch asset definition. 331 AssetDefinition* pAssetDefinition = *moduleAssets.begin(); 332 333 // Remove this asset. 334 removeDeclaredAsset( pAssetDefinition->mAssetId ); 335 } 336 337 // Info. 338 if ( mEchoInfo ) 339 Con::printSeparator(); 340 341 return true; 342} 343 344//----------------------------------------------------------------------------- 345 346bool AssetManager::removeDeclaredAsset( const char* pAssetId ) 347{ 348 // Debug Profiling. 349 PROFILE_SCOPE(AssetManager_RemoveSingleDeclaredAsset); 350 351 // Sanity! 352 AssertFatal( pAssetId != NULL, "Cannot remove single declared asset using NULL asset Id." ); 353 354 // Fetch asset Id. 355 StringTableEntry assetId = StringTable->insert( pAssetId ); 356 357 // Find declared asset. 358 typeDeclaredAssetsHash::iterator declaredAssetItr = mDeclaredAssets.find( assetId ); 359 360 // Did we find the declared asset? 361 if ( declaredAssetItr == mDeclaredAssets.end() ) 362 { 363 // No, so warn. 364 Con::warnf( "Asset Manager: Cannot remove single asset Id '%s' it could not be found.", assetId ); 365 return false; 366 } 367 368 // Fetch asset definition. 369 AssetDefinition* pAssetDefinition = declaredAssetItr->value; 370 371 // Is the asset private? 372 if ( !pAssetDefinition->mAssetPrivate ) 373 { 374 // No, so fetch module assets. 375 ModuleDefinition::typeModuleAssetsVector& moduleAssets = pAssetDefinition->mpModuleDefinition->getModuleAssets(); 376 377 // Remove module asset. 378 for ( ModuleDefinition::typeModuleAssetsVector::iterator moduleAssetItr = moduleAssets.begin(); moduleAssetItr != moduleAssets.end(); ++moduleAssetItr ) 379 { 380 if ( *moduleAssetItr == pAssetDefinition ) 381 { 382 moduleAssets.erase( moduleAssetItr ); 383 break; 384 } 385 } 386 387 // Remove asset dependencies. 388 removeAssetDependencies( pAssetId ); 389 } 390 391 // Do we have an asset loaded? 392 if ( pAssetDefinition->mpAssetBase != NULL ) 393 { 394 // Yes, so delete it. 395 // NOTE: If anything is using this then this'll cause a crash. Objects should always use safe reference methods however. 396 pAssetDefinition->mpAssetBase->deleteObject(); 397 } 398 399 // Remove from declared assets. 400 mDeclaredAssets.erase( declaredAssetItr ); 401 402 // Info. 403 if ( mEchoInfo ) 404 { 405 Con::printf( "Asset Manager: Removing Asset Id '%s' of type '%s' in asset file '%s'.", 406 pAssetDefinition->mAssetId, 407 pAssetDefinition->mAssetType, 408 pAssetDefinition->mAssetBaseFilePath ); 409 } 410 411 // Destroy asset definition. 412 delete pAssetDefinition; 413 414 return true; 415} 416 417//----------------------------------------------------------------------------- 418 419StringTableEntry AssetManager::getAssetName( const char* pAssetId ) 420{ 421 // Find asset definition. 422 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 423 424 // Did we find the asset? 425 if ( pAssetDefinition == NULL ) 426 { 427 // No, so warn. 428 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 429 return NULL; 430 } 431 432 return pAssetDefinition->mAssetName; 433} 434 435//----------------------------------------------------------------------------- 436 437StringTableEntry AssetManager::getAssetDescription( const char* pAssetId ) 438{ 439 // Find asset definition. 440 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 441 442 // Did we find the asset? 443 if ( pAssetDefinition == NULL ) 444 { 445 // No, so warn. 446 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 447 return NULL; 448 } 449 450 return pAssetDefinition->mAssetDescription; 451} 452 453//----------------------------------------------------------------------------- 454 455StringTableEntry AssetManager::getAssetCategory( const char* pAssetId ) 456{ 457 // Find asset definition. 458 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 459 460 // Did we find the asset? 461 if ( pAssetDefinition == NULL ) 462 { 463 // No, so warn. 464 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 465 return NULL; 466 } 467 468 return pAssetDefinition->mAssetCategory; 469} 470 471//----------------------------------------------------------------------------- 472 473StringTableEntry AssetManager::getAssetType( const char* pAssetId ) 474{ 475 // Find asset definition. 476 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 477 478 // Did we find the asset? 479 if ( pAssetDefinition == NULL ) 480 { 481 // No, so warn. 482 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 483 return NULL; 484 } 485 486 return pAssetDefinition->mAssetType; 487} 488 489//----------------------------------------------------------------------------- 490 491StringTableEntry AssetManager::getAssetFilePath( const char* pAssetId ) 492{ 493 // Find asset definition. 494 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 495 496 // Did we find the asset? 497 if ( pAssetDefinition == NULL ) 498 { 499 // No, so warn. 500 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 501 return StringTable->EmptyString(); 502 } 503 504 return pAssetDefinition->mAssetBaseFilePath; 505} 506 507//----------------------------------------------------------------------------- 508 509StringTableEntry AssetManager::getAssetPath( const char* pAssetId ) 510{ 511 // Debug Profiling. 512 PROFILE_SCOPE(AssetManager_GetAssetPath); 513 514 // Fetch asset file-path. 515 StringTableEntry assetFilePath = getAssetFilePath( pAssetId ); 516 517 // Finish if no file-path. 518 if ( assetFilePath == StringTable->EmptyString() ) 519 return assetFilePath; 520 521 // Find the final slash which should be just before the file. 522 const char* pFinalSlash = dStrrchr( assetFilePath, '/' ); 523 524 // Sanity! 525 AssertFatal( pFinalSlash != NULL, "Should always be able to find final slash in the asset file-path." ); 526 527 // Fetch asset path. 528 return StringTable->insertn( assetFilePath, (U32)(pFinalSlash - assetFilePath) ); 529} 530 531//----------------------------------------------------------------------------- 532 533ModuleDefinition* AssetManager::getAssetModuleDefinition( const char* pAssetId ) 534{ 535 // Find asset definition. 536 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 537 538 // Did we find the asset? 539 if ( pAssetDefinition == NULL ) 540 { 541 // No, so warn. 542 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 543 return NULL; 544 } 545 546 return pAssetDefinition->mpModuleDefinition; 547} 548 549//----------------------------------------------------------------------------- 550 551bool AssetManager::isAssetInternal( const char* pAssetId ) 552{ 553 // Find asset definition. 554 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 555 556 // Did we find the asset? 557 if ( pAssetDefinition == NULL ) 558 { 559 // No, so warn. 560 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 561 return false; 562 } 563 564 return pAssetDefinition->mAssetInternal; 565} 566 567//----------------------------------------------------------------------------- 568 569bool AssetManager::isAssetPrivate( const char* pAssetId ) 570{ 571 // Find asset definition. 572 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 573 574 // Did we find the asset? 575 if ( pAssetDefinition == NULL ) 576 { 577 // No, so warn. 578 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 579 return false; 580 } 581 582 return pAssetDefinition->mAssetPrivate; 583} 584 585//----------------------------------------------------------------------------- 586 587bool AssetManager::isAssetAutoUnload( const char* pAssetId ) 588{ 589 // Find asset definition. 590 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 591 592 // Did we find the asset? 593 if ( pAssetDefinition == NULL ) 594 { 595 // No, so warn. 596 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 597 return false; 598 } 599 600 return pAssetDefinition->mAssetAutoUnload; 601} 602 603//----------------------------------------------------------------------------- 604 605bool AssetManager::isAssetLoaded( const char* pAssetId ) 606{ 607 // Find asset definition. 608 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 609 610 // Did we find the asset? 611 if ( pAssetDefinition == NULL ) 612 { 613 // No, so warn. 614 Con::warnf( "Asset Manager: Cannot find asset Id '%s'.", pAssetId ); 615 return false; 616 } 617 618 return pAssetDefinition->mpAssetBase != NULL; 619} 620 621 622//----------------------------------------------------------------------------- 623 624bool AssetManager::isDeclaredAsset( const char* pAssetId ) 625{ 626 return findAsset( pAssetId ) != NULL; 627} 628 629//----------------------------------------------------------------------------- 630 631bool AssetManager::doesAssetDependOn( const char* pAssetId, const char* pDependsOnAssetId ) 632{ 633 // Debug Profiling. 634 PROFILE_SCOPE(AssetManager_DoesAssetDependOn); 635 636 // Sanity! 637 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 638 AssertFatal( pDependsOnAssetId != NULL, "Cannot use NULL depends-on asset Id." ); 639 640 // Fetch asset Id. 641 StringTableEntry assetId = StringTable->insert( pAssetId ); 642 643 // Fetch depends-on asset Id. 644 StringTableEntry dependsOnAssetId = StringTable->insert( pDependsOnAssetId ); 645 646 // Find depends-on entry. 647 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find( assetId ); 648 649 // Iterate all dependencies. 650 while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == assetId ) 651 { 652 // Finish if a depends on. 653 if ( dependsOnItr->value == dependsOnAssetId ) 654 return true; 655 656 // Next dependency. 657 dependsOnItr++; 658 } 659 660 return false; 661} 662 663//----------------------------------------------------------------------------- 664 665bool AssetManager::isAssetDependedOn( const char* pAssetId, const char* pDependedOnByAssetId ) 666{ 667 // Debug Profiling. 668 PROFILE_SCOPE(AssetManager_IsAssetDependedOn); 669 670 // Sanity! 671 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 672 AssertFatal( pDependedOnByAssetId != NULL, "Cannot use NULL depended-on-by asset Id." ); 673 674 // Fetch asset Id. 675 StringTableEntry assetId = StringTable->insert( pAssetId ); 676 677 // Fetch depended-on-by asset Id. 678 StringTableEntry dependedOnByAssetId = StringTable->insert( pDependedOnByAssetId ); 679 680 // Find depended-on-by entry. 681 typeAssetDependsOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find(assetId); 682 683 // Iterate all dependencies. 684 while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId ) 685 { 686 // Finish if depended-on. 687 if ( dependedOnItr->value == dependedOnByAssetId ) 688 return true; 689 690 // Next dependency. 691 dependedOnItr++; 692 } 693 694 return false; 695} 696 697//----------------------------------------------------------------------------- 698 699bool AssetManager::isReferencedAsset( const char* pAssetId ) 700{ 701 // Debug Profiling. 702 PROFILE_SCOPE(AssetManager_IsReferencedAsset); 703 704 // Sanity! 705 AssertFatal( pAssetId != NULL, "Cannot check if NULL asset Id is referenced." ); 706 707 // Fetch asset Id. 708 StringTableEntry assetId = StringTable->insert( pAssetId ); 709 710 // Is asset Id the correct format? 711 if ( StringUnit::getUnitCount( assetId, ASSET_SCOPE_TOKEN ) != 2 ) 712 { 713 // No, so warn. 714 Con::warnf( "Asset Manager: Cannot check if asset Id '%s' is referenced as it is not the correct format.", assetId ); 715 return false; 716 } 717 718 return mReferencedAssets.count( assetId ) > 0; 719} 720 721//----------------------------------------------------------------------------- 722 723bool AssetManager::renameDeclaredAsset( const char* pAssetIdFrom, const char* pAssetIdTo ) 724{ 725 // Debug Profiling. 726 PROFILE_SCOPE(AssetManager_RenameDeclaredAsset); 727 728 // Sanity! 729 AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." ); 730 AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." ); 731 732 // Fetch asset Ids. 733 StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom ); 734 StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo ); 735 736 // Is asset Id from the correct format? 737 if ( StringUnit::getUnitCount( assetIdFrom, ASSET_SCOPE_TOKEN ) != 2 ) 738 { 739 // No, so warn. 740 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as source asset Id is not the correct format.", assetIdFrom, assetIdTo ); 741 return false; 742 } 743 744 // Is asset Id to the correct format? 745 if ( StringUnit::getUnitCount( assetIdTo, ASSET_SCOPE_TOKEN ) != 2 ) 746 { 747 // No, so warn. 748 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as target asset Id is not the correct format.", assetIdFrom, assetIdTo ); 749 return false; 750 } 751 752 // Does the asset Id from exist? 753 if ( !mDeclaredAssets.contains( assetIdFrom ) ) 754 { 755 // No, so warn. 756 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as source asset Id is not declared.", assetIdFrom, assetIdTo ); 757 return false; 758 } 759 760 // Does the asset Id to exist? 761 if ( mDeclaredAssets.contains( assetIdTo ) ) 762 { 763 // No, so warn. 764 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as target asset Id is already declared.", assetIdFrom, assetIdTo ); 765 return false; 766 } 767 768 // Split module Ids from asset Ids. 769 StringTableEntry moduleIdFrom = StringTable->insert( StringUnit::getUnit( assetIdFrom, 0, ASSET_SCOPE_TOKEN ) ); 770 StringTableEntry moduleIdTo = StringTable->insert( StringUnit::getUnit( assetIdTo, 0, ASSET_SCOPE_TOKEN ) ); 771 772 // Are the module Ids the same? 773 if ( moduleIdFrom != moduleIdTo ) 774 { 775 // No, so warn. 776 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the module Id cannot be changed.", assetIdFrom, assetIdTo ); 777 return false; 778 } 779 780 // Find asset definition. 781 typeDeclaredAssetsHash::iterator assetDefinitionItr = mDeclaredAssets.find( assetIdFrom ); 782 783 // Sanity! 784 AssertFatal( assetDefinitionItr != mDeclaredAssets.end(), "Asset Manager: Failed to find asset." ); 785 786 // Fetch asset definition. 787 AssetDefinition* pAssetDefinition = assetDefinitionItr->value; 788 789 // Is this a private asset? 790 if ( pAssetDefinition->mAssetPrivate ) 791 { 792 // Yes, so warn. 793 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the source asset is private.", assetIdFrom, assetIdTo ); 794 return false; 795 } 796 797 // Setup declared update visitor. 798 TamlAssetDeclaredUpdateVisitor assetDeclaredUpdateVisitor; 799 assetDeclaredUpdateVisitor.setAssetIdFrom( assetIdFrom ); 800 assetDeclaredUpdateVisitor.setAssetIdTo( assetIdTo ); 801 802 // Update asset file declaration. 803 if ( !mTaml.parse( pAssetDefinition->mAssetBaseFilePath, assetDeclaredUpdateVisitor ) ) 804 { 805 // No, so warn. 806 Con::warnf("Asset Manager: Cannot rename declared asset Id '%s' to asset Id '%s' as the declared asset file could not be parsed: %s", 807 assetIdFrom, assetIdTo, pAssetDefinition->mAssetBaseFilePath ); 808 return false; 809 } 810 811 // Update asset definition. 812 pAssetDefinition->mAssetId = assetIdTo; 813 pAssetDefinition->mAssetName = StringTable->insert( StringUnit::getUnit( assetIdTo, 1, ASSET_SCOPE_TOKEN ) ); 814 815 // Reinsert declared asset. 816 mDeclaredAssets.erase( assetIdFrom ); 817 mDeclaredAssets.insert( assetIdTo, pAssetDefinition ); 818 819 // Info. 820 if ( mEchoInfo ) 821 { 822 Con::printf( "Asset Manager: Renaming declared Asset Id '%s' to Asset Id '%s'.", assetIdFrom, assetIdTo ); 823 Con::printSeparator(); 824 } 825 826 // Rename asset dependencies. 827 renameAssetDependencies( assetIdFrom, assetIdTo ); 828 829 // Do we have an asset tags manifest? 830 if ( !mAssetTagsManifest.isNull() ) 831 { 832 // Yes, so rename any assets. 833 mAssetTagsManifest->renameAssetId( pAssetIdFrom, pAssetIdTo ); 834 835 // Save the asset tags. 836 saveAssetTags(); 837 } 838 839 return true; 840} 841 842//----------------------------------------------------------------------------- 843 844bool AssetManager::renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo ) 845{ 846 // Debug Profiling. 847 PROFILE_SCOPE(AssetManager_RenameReferencedAsset); 848 849 // Sanity! 850 AssertFatal( pAssetIdFrom != NULL, "Cannot rename from NULL asset Id." ); 851 AssertFatal( pAssetIdTo != NULL, "Cannot rename to NULL asset Id." ); 852 853 // Fetch asset Ids. 854 StringTableEntry assetIdFrom = StringTable->insert( pAssetIdFrom ); 855 StringTableEntry assetIdTo = StringTable->insert( pAssetIdTo ); 856 857 // Is asset Id from the correct format? 858 if ( StringUnit::getUnitCount( assetIdFrom, ASSET_SCOPE_TOKEN ) != 2 ) 859 { 860 // No, so warn. 861 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as source asset Id is not the correct format.", assetIdFrom, assetIdTo ); 862 return false; 863 } 864 865 // Is asset Id to the correct format? 866 if ( StringUnit::getUnitCount( assetIdTo, ASSET_SCOPE_TOKEN ) != 2 ) 867 { 868 // No, so warn. 869 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as target asset Id is not the correct format.", assetIdFrom, assetIdTo ); 870 return false; 871 } 872 873 // Does the asset Id to exist? 874 if ( !mDeclaredAssets.contains( assetIdTo ) ) 875 { 876 // No, so warn. 877 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as target asset Id is not declared.", assetIdFrom, assetIdTo ); 878 return false; 879 } 880 881 // Rename asset references. 882 renameAssetReferences( assetIdFrom, assetIdTo ); 883 884 // Info. 885 if ( mEchoInfo ) 886 Con::printSeparator(); 887 888 return true; 889} 890 891//----------------------------------------------------------------------------- 892 893bool AssetManager::releaseAsset( const char* pAssetId ) 894{ 895 // Debug Profiling. 896 PROFILE_SCOPE(AssetManager_ReleaseAsset); 897 898 // Sanity! 899 AssertFatal( pAssetId != NULL, "Cannot release NULL asset Id." ); 900 901 // Find asset. 902 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 903 904 // Did we find the asset? 905 if ( pAssetDefinition == NULL ) 906 { 907 // No, so warn. 908 Con::warnf( "Asset Manager: Failed to release asset Id '%s' as it does not exist.", pAssetId ); 909 return false; 910 } 911 912 // Is the asset loaded? 913 if ( pAssetDefinition->mpAssetBase == NULL ) 914 { 915 // No, so warn. 916 Con::warnf( "Asset Manager: Failed to release asset Id '%s' as it is not acquired.", pAssetId ); 917 return false; 918 } 919 920 // Info. 921 if ( mEchoInfo ) 922 { 923 Con::printSeparator(); 924 Con::printf( "Asset Manager: Started releasing Asset Id '%s'...", pAssetId ); 925 } 926 927 // Release asset reference. 928 if ( pAssetDefinition->mpAssetBase->releaseAssetReference() ) 929 { 930 // Are we ignoring auto-unloaded assets? 931 if ( mIgnoreAutoUnload ) 932 { 933 // Yes, so info. 934 if ( mEchoInfo ) 935 { 936 Con::printf( "Asset Manager: > Releasing to idle state." ); 937 } 938 } 939 else 940 { 941 // No, so info. 942 if ( mEchoInfo ) 943 { 944 Con::printf( "Asset Manager: > Unload the asset from memory." ); 945 } 946 947 // Unload the asset. 948 unloadAsset( pAssetDefinition ); 949 } 950 } 951 // Info. 952 else if ( mEchoInfo ) 953 { 954 Con::printf( "Asset Manager: > Reference count now '%d'.", pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() ); 955 } 956 957 // Info. 958 if ( mEchoInfo ) 959 { 960 Con::printf( "Asset Manager: > Finished releasing Asset Id '%s'.", pAssetId ); 961 Con::printSeparator(); 962 } 963 964 return true; 965} 966 967//----------------------------------------------------------------------------- 968 969void AssetManager::purgeAssets( void ) 970{ 971 // Debug Profiling. 972 PROFILE_SCOPE(AssetManager_PurgeAssets); 973 974 // Info. 975 if ( mEchoInfo ) 976 { 977 Con::printf( "Asset Manager: Started purging assets..." ); 978 } 979 980 // Iterate asset definitions. 981 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 982 { 983 // Fetch asset definition. 984 AssetDefinition* pAssetDefinition = assetItr->value; 985 986 // Skip asset if private, not loaded or referenced. 987 if ( pAssetDefinition->mAssetPrivate || 988 pAssetDefinition->mpAssetBase == NULL || 989 pAssetDefinition->mpAssetBase->getAcquiredReferenceCount() > 0 ) 990 continue; 991 992 // Info. 993 if ( mEchoInfo ) 994 { 995 Con::printf( "Asset Manager: Purging asset Id '%s'...", pAssetDefinition->mAssetId ); 996 } 997 998 // Unload the asset. 999 unloadAsset( pAssetDefinition ); 1000 } 1001 1002 // Info. 1003 if ( mEchoInfo ) 1004 { 1005 Con::printf( "Asset Manager: ... Finished purging assets." ); 1006 } 1007} 1008 1009//----------------------------------------------------------------------------- 1010 1011bool AssetManager::deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies ) 1012{ 1013 // Debug Profiling. 1014 PROFILE_SCOPE(AssetManager_DeleteAsset); 1015 1016 // Sanity! 1017 AssertFatal( pAssetId != NULL, "Cannot delete NULL asset Id." ); 1018 1019 // Find asset. 1020 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 1021 1022 // Did we find the asset? 1023 if ( pAssetDefinition == NULL ) 1024 { 1025 // No, so warn. 1026 Con::warnf( "Asset Manager: Failed to delete asset Id '%s' as it does not exist.", pAssetId ); 1027 return false; 1028 } 1029 1030 // Info. 1031 if ( mEchoInfo ) 1032 { 1033 Con::printSeparator(); 1034 Con::printf( "Asset Manager: Started deleting Asset Id '%s'...", pAssetId ); 1035 } 1036 1037 // Fetch asset Id. 1038 StringTableEntry assetId = StringTable->insert( pAssetId ); 1039 1040 // Are we deleting dependencies? 1041 if ( deleteDependencies ) 1042 { 1043 Vector<typeAssetId> dependantAssets; 1044 1045 // Yes, so find depended-on-by entry. 1046 typeAssetDependsOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find( assetId ); 1047 1048 // Iterate all dependencies. 1049 while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId ) 1050 { 1051 // Store asset Id. 1052 dependantAssets.push_back( dependedOnItr->value ); 1053 1054 // Next dependency. 1055 dependedOnItr++; 1056 } 1057 1058 // Do we have any dependants? 1059 if ( dependantAssets.size() > 0 ) 1060 { 1061 // Yes, so iterate dependants. 1062 for( Vector<typeAssetId>::const_iterator assetItr = dependantAssets.begin(); assetItr != dependantAssets.end(); ++assetItr ) 1063 { 1064 StringTableEntry dependentAssetId = *assetItr; 1065 1066 // Info. 1067 if ( mEchoInfo ) 1068 { 1069 Con::printSeparator(); 1070 Con::printf( "Asset Manager: Deleting Asset Id '%s' dependant of '%s.'", pAssetId, dependentAssetId ); 1071 } 1072 1073 // Delete dependant. 1074 deleteAsset( dependentAssetId, deleteLooseFiles, deleteDependencies ); 1075 } 1076 } 1077 } 1078 1079 // Remove asset references. 1080 removeAssetReferences( assetId ); 1081 1082 // Are we deleting loose files? 1083 if ( deleteLooseFiles ) 1084 { 1085 // Yes, so remove loose files. 1086 Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles; 1087 for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr ) 1088 { 1089 // Fetch loose file. 1090 StringTableEntry looseFile = *looseFileItr; 1091 1092 // Delete the loose file. 1093 if ( !dFileDelete( looseFile ) ) 1094 { 1095 // Failed so warn. 1096 Con::warnf( "Asset Manager: Failed to delete the loose file '%s' while deleting asset Id '%s'.", looseFile, pAssetId ); 1097 } 1098 } 1099 } 1100 1101 // Fetch asset definition file. 1102 StringTableEntry assetDefinitionFile = pAssetDefinition->mAssetBaseFilePath; 1103 1104 // Remove reference here as we're about to remove the declared asset. 1105 pAssetDefinition = NULL; 1106 1107 // Remove asset. 1108 removeDeclaredAsset( pAssetId ); 1109 1110 // Delete the asset definition file. 1111 if ( !dFileDelete( assetDefinitionFile ) ) 1112 { 1113 // Failed so warn. 1114 Con::warnf( "Asset Manager: Failed to delete the asset definition file '%s' while deleting asset Id '%s'.", assetDefinitionFile, pAssetId ); 1115 } 1116 1117 // Info. 1118 if ( mEchoInfo ) 1119 { 1120 Con::printSeparator(); 1121 Con::printf( "Asset Manager: Finished deleting Asset Id '%s'.", pAssetId ); 1122 } 1123 1124 return true; 1125} 1126 1127//----------------------------------------------------------------------------- 1128 1129bool AssetManager::refreshAsset( const char* pAssetId ) 1130{ 1131 // Debug Profiling. 1132 PROFILE_SCOPE(AssetManager_RefreshAsset); 1133 1134 // Sanity! 1135 AssertFatal( pAssetId != NULL, "Cannot refresh NULL asset Id." ); 1136 1137 // Find asset. 1138 AssetDefinition* pAssetDefinition = findAsset( pAssetId ); 1139 1140 // Did we find the asset? 1141 if ( pAssetDefinition == NULL ) 1142 { 1143 // No, so warn. 1144 Con::warnf( "Asset Manager: Failed to refresh asset Id '%s' as it does not exist.", pAssetId ); 1145 return false; 1146 } 1147 1148 // Info. 1149 if ( mEchoInfo ) 1150 { 1151 Con::printSeparator(); 1152 Con::printf( "Asset Manager: Started refreshing Asset Id '%s'...", pAssetId ); 1153 } 1154 1155 // Fetch asset Id. 1156 StringTableEntry assetId = StringTable->insert( pAssetId ); 1157 1158 // Is the asset private? 1159 if ( pAssetDefinition->mAssetPrivate ) 1160 { 1161 // Yes, so notify asset of asset refresh only. 1162 pAssetDefinition->mpAssetBase->onAssetRefresh(); 1163 1164 // Asset refresh notifications. 1165 for( typeAssetPtrRefreshHash::iterator refreshNotifyItr = mAssetPtrRefreshNotifications.begin(); refreshNotifyItr != mAssetPtrRefreshNotifications.end(); ++refreshNotifyItr ) 1166 { 1167 // Fetch pointed asset. 1168 StringTableEntry pointedAsset = refreshNotifyItr->key->getAssetId(); 1169 1170 // Ignore if the pointed asset is not the asset or a dependency. 1171 if ( pointedAsset == StringTable->EmptyString() || ( pointedAsset != assetId && !doesAssetDependOn( pointedAsset, assetId ) ) ) 1172 continue; 1173 1174 // Perform refresh notification callback. 1175 refreshNotifyItr->value->onAssetRefreshed( refreshNotifyItr->key ); 1176 } 1177 } 1178 // Is the asset definition allowed to refresh? 1179 else if ( pAssetDefinition->mAssetRefreshEnable ) 1180 { 1181 // Yes, so fetch the asset. 1182 AssetBase* pAssetBase = pAssetDefinition->mpAssetBase; 1183 1184 // Is the asset loaded? 1185 if ( pAssetBase != NULL ) 1186 { 1187 // Yes, so notify asset of asset refresh. 1188 pAssetBase->onAssetRefresh(); 1189 1190 // Save asset. 1191 mTaml.write( pAssetBase, pAssetDefinition->mAssetBaseFilePath ); 1192 1193 // Remove asset dependencies. 1194 removeAssetDependencies( pAssetId ); 1195 1196 // Find any new dependencies. 1197 TamlAssetDeclaredVisitor assetDeclaredVisitor; 1198 1199 // Parse the filename. 1200 if ( !mTaml.parse( pAssetDefinition->mAssetBaseFilePath, assetDeclaredVisitor ) ) 1201 { 1202 // Warn. 1203 Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.\nDependencies are now incorrect!", pAssetDefinition->mAssetBaseFilePath ); 1204 return false; 1205 } 1206 1207 // Fetch asset dependencies. 1208 TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies(); 1209 1210 // Are there any asset dependences? 1211 if ( assetDependencies.size() > 0 ) 1212 { 1213 // Yes, so iterate dependencies. 1214 for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr ) 1215 { 1216 // Fetch dependency asset Id. 1217 StringTableEntry dependencyAssetId = *assetDependencyItr; 1218 1219 // Insert depends-on. 1220 mAssetDependsOn.insertEqual( assetId, dependencyAssetId ); 1221 1222 // Insert is-depended-on. 1223 mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId ); 1224 } 1225 } 1226 1227 // Fetch asset loose files. 1228 TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles(); 1229 1230 // Clear any existing loose files. 1231 pAssetDefinition->mAssetLooseFiles.clear(); 1232 1233 // Are there any loose files? 1234 if ( assetLooseFiles.size() > 0 ) 1235 { 1236 // Yes, so iterate loose files. 1237 for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr ) 1238 { 1239 // Store loose file. 1240 pAssetDefinition->mAssetLooseFiles.push_back( *assetLooseFileItr ); 1241 } 1242 } 1243 1244 // Asset refresh notifications. 1245 for( typeAssetPtrRefreshHash::iterator refreshNotifyItr = mAssetPtrRefreshNotifications.begin(); refreshNotifyItr != mAssetPtrRefreshNotifications.end(); ++refreshNotifyItr ) 1246 { 1247 // Fetch pointed asset. 1248 StringTableEntry pointedAsset = refreshNotifyItr->key->getAssetId(); 1249 1250 // Ignore if the pointed asset is not the asset or a dependency. 1251 if ( pointedAsset == StringTable->EmptyString() || ( pointedAsset != assetId && !doesAssetDependOn( pointedAsset, assetId ) ) ) 1252 continue; 1253 1254 // Perform refresh notification callback. 1255 refreshNotifyItr->value->onAssetRefreshed( refreshNotifyItr->key ); 1256 } 1257 1258 // Find is-depends-on entry. 1259 typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find( assetId ); 1260 1261 // Is asset depended on? 1262 if ( isDependedOnItr != mAssetIsDependedOn.end() ) 1263 { 1264 // Yes, so compiled them. 1265 Vector<typeAssetId> dependedOn; 1266 1267 // Iterate all dependencies. 1268 while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == assetId ) 1269 { 1270 dependedOn.push_back( isDependedOnItr->value ); 1271 1272 // Next dependency. 1273 isDependedOnItr++; 1274 } 1275 1276 // Refresh depended-on assets. 1277 for ( Vector<typeAssetId>::iterator isDependedOnItr = dependedOn.begin(); isDependedOnItr != dependedOn.end(); ++isDependedOnItr ) 1278 { 1279 // Refresh dependency asset. 1280 refreshAsset( *isDependedOnItr ); 1281 } 1282 } 1283 } 1284 } 1285 1286 // Info. 1287 if ( mEchoInfo ) 1288 { 1289 Con::printSeparator(); 1290 Con::printf( "Asset Manager: Finished refreshing Asset Id '%s'.", pAssetId ); 1291 } 1292 1293 return true; 1294} 1295 1296//----------------------------------------------------------------------------- 1297 1298void AssetManager::refreshAllAssets( const bool includeUnloaded ) 1299{ 1300 // Debug Profiling. 1301 PROFILE_SCOPE(AssetManager_RefreshAllAssets); 1302 1303 // Info. 1304 if ( mEchoInfo ) 1305 { 1306 Con::printSeparator(); 1307 Con::printf( "Asset Manager: Started refreshing ALL assets." ); 1308 } 1309 1310 Vector<typeAssetId> assetsToRelease; 1311 1312 // Are we including unloaded assets? 1313 if ( includeUnloaded ) 1314 { 1315 // Yes, so prepare a list of assets to release and load them. 1316 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1317 { 1318 // Fetch asset Id. 1319 typeAssetId assetId = assetItr->key; 1320 1321 // Skip if asset is loaded. 1322 if ( assetItr->value->mpAssetBase != NULL ) 1323 continue; 1324 1325 // Note asset as needing a release. 1326 assetsToRelease.push_back( assetId ); 1327 1328 // Acquire the asset. 1329 acquireAsset<AssetBase>( assetId ); 1330 } 1331 } 1332 1333 // Refresh the current loaded assets. 1334 // NOTE: This will result in some assets being refreshed more than once due to asset dependencies. 1335 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1336 { 1337 // Skip private assets. 1338 if ( assetItr->value->mAssetPrivate ) 1339 continue; 1340 1341 // Refresh asset if it's loaded. 1342 refreshAsset( assetItr->key ); 1343 } 1344 1345 // Are we including unloaded assets? 1346 if ( includeUnloaded ) 1347 { 1348 // Yes, so release the assets we loaded. 1349 for( Vector<typeAssetId>::iterator assetItr = assetsToRelease.begin(); assetItr != assetsToRelease.end(); ++assetItr ) 1350 { 1351 releaseAsset( *assetItr ); 1352 } 1353 } 1354 1355 // Info. 1356 if ( mEchoInfo ) 1357 { 1358 Con::printSeparator(); 1359 Con::printf( "Asset Manager: Finished refreshing ALL assets." ); 1360 } 1361} 1362 1363//----------------------------------------------------------------------------- 1364 1365void AssetManager::registerAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase, AssetPtrCallback* pCallback ) 1366{ 1367 // Find an existing notification iterator. 1368 typeAssetPtrRefreshHash::iterator notificationItr = mAssetPtrRefreshNotifications.find( pAssetPtrBase ); 1369 1370 // Do we have one? 1371 if ( notificationItr != mAssetPtrRefreshNotifications.end() ) 1372 { 1373 // Yes, so update the callback. 1374 notificationItr->value = pCallback; 1375 return; 1376 } 1377 1378 // No, so add one. 1379 mAssetPtrRefreshNotifications.insert( pAssetPtrBase, pCallback ); 1380} 1381 1382//----------------------------------------------------------------------------- 1383 1384void AssetManager::unregisterAssetPtrRefreshNotify( AssetPtrBase* pAssetPtrBase ) 1385{ 1386 mAssetPtrRefreshNotifications.erase( pAssetPtrBase ); 1387} 1388 1389//----------------------------------------------------------------------------- 1390 1391bool AssetManager::loadAssetTags( ModuleDefinition* pModuleDefinition ) 1392{ 1393 // Sanity! 1394 AssertFatal( pModuleDefinition != NULL, "Cannot load asset tags manifest using a NULL module definition" ); 1395 1396 // Expand manifest location. 1397 char assetTagsManifestFilePathBuffer[1024]; 1398 Con::expandPath( assetTagsManifestFilePathBuffer, sizeof(assetTagsManifestFilePathBuffer), pModuleDefinition->getAssetTagsManifest() ); 1399 1400 // Do we already have a manifest? 1401 if ( !mAssetTagsManifest.isNull() ) 1402 { 1403 // Yes, so warn. 1404 Con::warnf( "Asset Manager: Cannot load asset tags manifest from module '%s' as one is already loaded.", pModuleDefinition->getSignature() ); 1405 return false; 1406 } 1407 1408 // Is the specified file valid? 1409 if ( Platform::isFile( assetTagsManifestFilePathBuffer ) ) 1410 { 1411 // Yes, so read asset tags manifest. 1412 mAssetTagsManifest = mTaml.read<AssetTagsManifest>( assetTagsManifestFilePathBuffer ); 1413 1414 // Did we read the manifest? 1415 if ( mAssetTagsManifest.isNull() ) 1416 { 1417 // No, so warn. 1418 Con::warnf( "Asset Manager: Failed to load asset tags manifest '%s' from module '%s'.", assetTagsManifestFilePathBuffer, pModuleDefinition->getSignature() ); 1419 return false; 1420 } 1421 1422 // Set asset tags module definition. 1423 mAssetTagsModuleDefinition = pModuleDefinition; 1424 } 1425 else 1426 { 1427 // No, so generate a new asset tags manifest. 1428 mAssetTagsManifest = new AssetTagsManifest(); 1429 mAssetTagsManifest->registerObject(); 1430 1431 // Set asset tags module definition. 1432 mAssetTagsModuleDefinition = pModuleDefinition; 1433 1434 // Save the asset tags. 1435 saveAssetTags(); 1436 } 1437 1438 return true; 1439} 1440 1441//----------------------------------------------------------------------------- 1442 1443bool AssetManager::saveAssetTags( void ) 1444{ 1445 // Do we have an asset tags manifest? 1446 if ( mAssetTagsManifest.isNull() || mAssetTagsModuleDefinition.isNull() ) 1447 { 1448 // No, so warn. 1449 Con::warnf( "Asset Manager: Failed to save asset tags manifest as one is not loaded." ); 1450 return false; 1451 } 1452 1453 // Expand manifest location. 1454 char assetTagsManifestFilePathBuffer[1024]; 1455 Con::expandPath( assetTagsManifestFilePathBuffer, sizeof(assetTagsManifestFilePathBuffer), mAssetTagsModuleDefinition->getAssetTagsManifest() ); 1456 1457 // Save asset tags manifest. 1458 if ( !mTaml.write( mAssetTagsManifest, assetTagsManifestFilePathBuffer ) ) 1459 { 1460 // Failed so warn. 1461 Con::warnf( "Asset Manager: Failed to save asset tags manifest '%s' from module '%s'.", assetTagsManifestFilePathBuffer, mAssetTagsModuleDefinition->getSignature() ); 1462 return false; 1463 } 1464 1465 return true; 1466} 1467 1468//----------------------------------------------------------------------------- 1469 1470bool AssetManager::restoreAssetTags( void ) 1471{ 1472 // Do we already have a manifest? 1473 if ( mAssetTagsManifest.isNull() ) 1474 { 1475 // No, so warn. 1476 Con::warnf( "Asset Manager: Cannot restore asset tags manifest as one is not already loaded." ); 1477 return false; 1478 } 1479 1480 // Sanity! 1481 AssertFatal( mAssetTagsModuleDefinition != NULL, "Cannot restore asset tags manifest as module definition is NULL." ); 1482 1483 // Delete existing asset tags manifest. 1484 mAssetTagsManifest->deleteObject(); 1485 1486 // Reload asset tags manifest. 1487 return loadAssetTags( mAssetTagsModuleDefinition ); 1488} 1489 1490//----------------------------------------------------------------------------- 1491 1492S32 QSORT_CALLBACK descendingAssetDefinitionLoadCount(const void* a, const void* b) 1493{ 1494 // Debug Profiling. 1495 PROFILE_SCOPE(AssetManager_DescendingAssetDefinitionLoadCount); 1496 1497 // Fetch asset definitions. 1498 const AssetDefinition* pAssetDefinitionA = *(AssetDefinition**)a; 1499 const AssetDefinition* pAssetDefinitionB = *(AssetDefinition**)b; 1500 1501 // Sort. 1502 return pAssetDefinitionB->mAssetLoadedCount - pAssetDefinitionA->mAssetLoadedCount; 1503} 1504 1505//----------------------------------------------------------------------------- 1506 1507void AssetManager::dumpDeclaredAssets( void ) const 1508{ 1509 Vector<const AssetDefinition*> assetDefinitions; 1510 1511 // Iterate asset definitions. 1512 for( typeDeclaredAssetsHash::const_iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1513 { 1514 assetDefinitions.push_back( assetItr->value ); 1515 } 1516 1517 // Sort asset definitions. 1518 dQsort( assetDefinitions.address(), assetDefinitions.size(), sizeof(const AssetDefinition*), descendingAssetDefinitionLoadCount ); 1519 1520 // Info. 1521 Con::printSeparator(); 1522 Con::printf( "Asset Manager: %d declared asset(s) dump as follows:", mDeclaredAssets.size() ); 1523 Con::printBlankLine(); 1524 1525 // Iterate sorted asset definitions. 1526 for ( Vector<const AssetDefinition*>::iterator assetItr = assetDefinitions.begin(); assetItr != assetDefinitions.end(); ++assetItr ) 1527 { 1528 // Fetch asset definition. 1529 const AssetDefinition* pAssetDefinition = *assetItr; 1530 1531 // Info. 1532 Con::printf( "AssetId:'%s', RefCount:%d, LoadCount:%d, UnloadCount:%d, AutoUnload:%d, Loaded:%d, Internal:%d, Private: %d, Type:'%s', Module/Version:'%s'/'%d', File:'%s'", 1533 pAssetDefinition->mAssetId, 1534 pAssetDefinition->mpAssetBase == NULL ? 0 : pAssetDefinition->mpAssetBase->getAcquiredReferenceCount(), 1535 pAssetDefinition->mAssetLoadedCount, 1536 pAssetDefinition->mAssetUnloadedCount, 1537 pAssetDefinition->mAssetAutoUnload, 1538 pAssetDefinition->mpAssetBase != NULL, 1539 pAssetDefinition->mAssetInternal, 1540 pAssetDefinition->mAssetPrivate, 1541 pAssetDefinition->mAssetType, 1542 pAssetDefinition->mpModuleDefinition->getModuleId(), 1543 pAssetDefinition->mpModuleDefinition->getVersionId(), 1544 pAssetDefinition->mAssetBaseFilePath ); 1545 } 1546 1547 // Info. 1548 Con::printSeparator(); 1549 Con::printBlankLine(); 1550} 1551 1552//----------------------------------------------------------------------------- 1553 1554S32 AssetManager::findAllAssets( AssetQuery* pAssetQuery, const bool ignoreInternal, const bool ignorePrivate ) 1555{ 1556 // Debug Profiling. 1557 PROFILE_SCOPE(AssetManager_FindAllAssets); 1558 1559 // Sanity! 1560 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1561 1562 // Reset result count. 1563 S32 resultCount = 0; 1564 1565 // Iterate declared assets. 1566 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1567 { 1568 // Fetch asset definition. 1569 AssetDefinition* pAssetDefinition = assetItr->value; 1570 1571 // Skip if internal and we're ignoring them. 1572 if ( ignoreInternal && pAssetDefinition->mAssetInternal ) 1573 continue; 1574 1575 // Skip if private and we're ignoring them. 1576 if ( ignorePrivate && pAssetDefinition->mAssetPrivate ) 1577 continue; 1578 1579 // Store as result. 1580 pAssetQuery->mAssetList.push_back( pAssetDefinition->mAssetId ); 1581 1582 // Increase result count. 1583 resultCount++; 1584 } 1585 1586 return resultCount; 1587} 1588 1589//----------------------------------------------------------------------------- 1590 1591S32 AssetManager::findAssetName( AssetQuery* pAssetQuery, const char* pAssetName, const bool partialName ) 1592{ 1593 // Debug Profiling. 1594 PROFILE_SCOPE(AssetManager_FindAssetName); 1595 1596 // Sanity! 1597 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1598 AssertFatal( pAssetName != NULL, "Cannot use NULL asset name." ); 1599 1600 // Reset asset name. 1601 StringTableEntry assetName = NULL; 1602 S32 partialAssetNameLength = 0; 1603 1604 // Are we doing partial name search? 1605 if ( partialName ) 1606 { 1607 // Yes, so fetch length of partial name. 1608 partialAssetNameLength = dStrlen( pAssetName ); 1609 } 1610 else 1611 { 1612 // No, so fetch asset name. 1613 assetName = StringTable->insert( pAssetName ); 1614 } 1615 1616 // Reset result count. 1617 S32 resultCount = 0; 1618 1619 // Iterate declared assets. 1620 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1621 { 1622 // Fetch asset definition. 1623 AssetDefinition* pAssetDefinition = assetItr->value; 1624 1625 // Are we doing partial name search? 1626 if ( partialName ) 1627 { 1628 // Yes, so fetch the length of this asset name. 1629 const S32 currentAssetNameLength = dStrlen( pAssetDefinition->mAssetName ); 1630 1631 // Skip if the query asset name is longer than the current asset name. 1632 if ( partialAssetNameLength > currentAssetNameLength ) 1633 continue; 1634 1635 // Skip if this is not the asset we want. 1636 if ( dStrnicmp( pAssetDefinition->mAssetName, pAssetName, partialAssetNameLength ) != 0 ) 1637 continue; 1638 } 1639 else 1640 { 1641 // No, so skip if this is not the asset we want. 1642 if ( assetName != pAssetDefinition->mAssetName ) 1643 continue; 1644 } 1645 1646 // Store as result. 1647 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1648 1649 // Increase result count. 1650 resultCount++; 1651 } 1652 1653 return resultCount; 1654} 1655 1656//----------------------------------------------------------------------------- 1657 1658S32 AssetManager::findAssetCategory( AssetQuery* pAssetQuery, const char* pAssetCategory, const bool assetQueryAsSource ) 1659{ 1660 // Debug Profiling. 1661 PROFILE_SCOPE(AssetManager_FindAssetCategory); 1662 1663 // Sanity! 1664 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1665 AssertFatal( pAssetCategory != NULL, "Cannot use NULL asset category." ); 1666 1667 // Fetch asset category. 1668 StringTableEntry assetCategory = StringTable->insert( pAssetCategory ); 1669 1670 // Reset result count. 1671 S32 resultCount = 0; 1672 1673 // Use asset-query as the source? 1674 if ( assetQueryAsSource ) 1675 { 1676 AssetQuery filteredAssets; 1677 1678 // Yes, so iterate asset query. 1679 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1680 { 1681 // Fetch asset definition. 1682 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1683 1684 // Skip if this is not the asset we want. 1685 if ( pAssetDefinition == NULL || 1686 pAssetDefinition->mAssetCategory != assetCategory ) 1687 continue; 1688 1689 // Store as result. 1690 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1691 1692 // Increase result count. 1693 resultCount++; 1694 } 1695 1696 // Set asset query. 1697 pAssetQuery->set( filteredAssets ); 1698 } 1699 else 1700 { 1701 // No, so iterate declared assets. 1702 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1703 { 1704 // Fetch asset definition. 1705 AssetDefinition* pAssetDefinition = assetItr->value; 1706 1707 // Skip if this is not the asset we want. 1708 if ( assetCategory != pAssetDefinition->mAssetCategory ) 1709 continue; 1710 1711 // Store as result. 1712 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1713 1714 // Increase result count. 1715 resultCount++; 1716 } 1717 } 1718 1719 return resultCount; 1720} 1721 1722S32 AssetManager::findAssetAutoUnload( AssetQuery* pAssetQuery, const bool assetAutoUnload, const bool assetQueryAsSource ) 1723{ 1724 // Debug Profiling. 1725 PROFILE_SCOPE(AssetManager_FindAssetAutoUnload); 1726 1727 // Sanity! 1728 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1729 1730 // Reset result count. 1731 S32 resultCount = 0; 1732 1733 // Use asset-query as the source? 1734 if ( assetQueryAsSource ) 1735 { 1736 AssetQuery filteredAssets; 1737 1738 // Yes, so iterate asset query. 1739 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1740 { 1741 // Fetch asset definition. 1742 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1743 1744 // Skip if this is not the asset we want. 1745 if ( pAssetDefinition == NULL || 1746 pAssetDefinition->mAssetAutoUnload != assetAutoUnload ) 1747 continue; 1748 1749 // Store as result. 1750 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1751 1752 // Increase result count. 1753 resultCount++; 1754 } 1755 1756 // Set asset query. 1757 pAssetQuery->set( filteredAssets ); 1758 } 1759 else 1760 { 1761 // No, so iterate declared assets. 1762 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1763 { 1764 // Fetch asset definition. 1765 AssetDefinition* pAssetDefinition = assetItr->value; 1766 1767 // Skip if this is not the asset we want. 1768 if ( assetAutoUnload != pAssetDefinition->mAssetAutoUnload ) 1769 continue; 1770 1771 // Store as result. 1772 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1773 1774 // Increase result count. 1775 resultCount++; 1776 } 1777 } 1778 1779 return resultCount; 1780} 1781 1782//----------------------------------------------------------------------------- 1783 1784S32 AssetManager::findAssetInternal( AssetQuery* pAssetQuery, const bool assetInternal, const bool assetQueryAsSource ) 1785{ 1786 // Debug Profiling. 1787 PROFILE_SCOPE(AssetManager_FindAssetInternal); 1788 1789 // Sanity! 1790 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1791 1792 // Reset result count. 1793 S32 resultCount = 0; 1794 1795 // Use asset-query as the source? 1796 if ( assetQueryAsSource ) 1797 { 1798 AssetQuery filteredAssets; 1799 1800 // Yes, so iterate asset query. 1801 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1802 { 1803 // Fetch asset definition. 1804 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1805 1806 // Skip if this is not the asset we want. 1807 if ( pAssetDefinition == NULL || 1808 pAssetDefinition->mAssetInternal != assetInternal ) 1809 continue; 1810 1811 // Store as result. 1812 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1813 1814 // Increase result count. 1815 resultCount++; 1816 } 1817 1818 // Set asset query. 1819 pAssetQuery->set( filteredAssets ); 1820 } 1821 else 1822 { 1823 // No, so iterate declared assets. 1824 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1825 { 1826 // Fetch asset definition. 1827 AssetDefinition* pAssetDefinition = assetItr->value; 1828 1829 // Skip if this is not the asset we want. 1830 if ( assetInternal != pAssetDefinition->mAssetInternal ) 1831 continue; 1832 1833 // Store as result. 1834 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1835 1836 // Increase result count. 1837 resultCount++; 1838 } 1839 } 1840 1841 return resultCount; 1842} 1843 1844//----------------------------------------------------------------------------- 1845 1846S32 AssetManager::findAssetPrivate( AssetQuery* pAssetQuery, const bool assetPrivate, const bool assetQueryAsSource ) 1847{ 1848 // Debug Profiling. 1849 PROFILE_SCOPE(AssetManager_FindAssetPrivate); 1850 1851 // Sanity! 1852 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1853 1854 // Reset result count. 1855 S32 resultCount = 0; 1856 1857 // Use asset-query as the source? 1858 if ( assetQueryAsSource ) 1859 { 1860 AssetQuery filteredAssets; 1861 1862 // Yes, so iterate asset query. 1863 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1864 { 1865 // Fetch asset definition. 1866 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1867 1868 // Skip if this is not the asset we want. 1869 if ( pAssetDefinition == NULL || 1870 pAssetDefinition->mAssetPrivate != assetPrivate ) 1871 continue; 1872 1873 // Store as result. 1874 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1875 1876 // Increase result count. 1877 resultCount++; 1878 } 1879 1880 // Set asset query. 1881 pAssetQuery->set( filteredAssets ); 1882 } 1883 else 1884 { 1885 // No, so iterate declared assets. 1886 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1887 { 1888 // Fetch asset definition. 1889 AssetDefinition* pAssetDefinition = assetItr->value; 1890 1891 // Skip if this is not the asset we want. 1892 if ( assetPrivate != pAssetDefinition->mAssetPrivate ) 1893 continue; 1894 1895 // Store as result. 1896 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1897 1898 // Increase result count. 1899 resultCount++; 1900 } 1901 } 1902 1903 return resultCount; 1904} 1905 1906//----------------------------------------------------------------------------- 1907 1908S32 AssetManager::findAssetType( AssetQuery* pAssetQuery, const char* pAssetType, const bool assetQueryAsSource ) 1909{ 1910 // Debug Profiling. 1911 PROFILE_SCOPE(AssetManager_FindAssetType); 1912 1913 // Sanity! 1914 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1915 AssertFatal( pAssetType != NULL, "Cannot use NULL asset type." ); 1916 1917 // Fetch asset type. 1918 StringTableEntry assetType = StringTable->insert( pAssetType ); 1919 1920 // Reset result count. 1921 S32 resultCount = 0; 1922 1923 // Use asset-query as the source? 1924 if ( assetQueryAsSource ) 1925 { 1926 AssetQuery filteredAssets; 1927 1928 // Yes, so iterate asset query. 1929 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 1930 { 1931 // Fetch asset definition. 1932 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 1933 1934 // Skip if this is not the asset we want. 1935 if ( pAssetDefinition == NULL || 1936 pAssetDefinition->mAssetType != assetType ) 1937 continue; 1938 1939 // Store as result. 1940 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 1941 1942 // Increase result count. 1943 resultCount++; 1944 } 1945 1946 // Set asset query. 1947 pAssetQuery->set( filteredAssets ); 1948 } 1949 else 1950 { 1951 // No, so iterate declared assets. 1952 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 1953 { 1954 // Fetch asset definition. 1955 AssetDefinition* pAssetDefinition = assetItr->value; 1956 1957 // Skip if this is not the asset we want. 1958 if ( assetType != pAssetDefinition->mAssetType ) 1959 continue; 1960 1961 // Store as result. 1962 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 1963 1964 // Increase result count. 1965 resultCount++; 1966 } 1967 } 1968 1969 return resultCount; 1970} 1971 1972//----------------------------------------------------------------------------- 1973 1974S32 AssetManager::findAssetDependsOn( AssetQuery* pAssetQuery, const char* pAssetId ) 1975{ 1976 // Debug Profiling. 1977 PROFILE_SCOPE(AssetManager_FindAssetDependsOn); 1978 1979 // Sanity! 1980 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 1981 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 1982 1983 // Fetch asset Id. 1984 StringTableEntry assetId = StringTable->insert( pAssetId ); 1985 1986 // Reset result count. 1987 S32 resultCount = 0; 1988 1989 // Find depends-on entry. 1990 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find( assetId ); 1991 1992 // Iterate all dependencies. 1993 while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == assetId ) 1994 { 1995 // Store as result. 1996 pAssetQuery->mAssetList.push_back(dependsOnItr->value); 1997 1998 // Next dependency. 1999 dependsOnItr++; 2000 2001 // Increase result count. 2002 resultCount++; 2003 } 2004 2005 return resultCount; 2006} 2007 2008//----------------------------------------------------------------------------- 2009 2010S32 AssetManager::findAssetIsDependedOn( AssetQuery* pAssetQuery, const char* pAssetId ) 2011{ 2012 // Debug Profiling. 2013 PROFILE_SCOPE(AssetManager_FindAssetIsDependedOn); 2014 2015 // Sanity! 2016 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2017 AssertFatal( pAssetId != NULL, "Cannot use NULL asset Id." ); 2018 2019 // Fetch asset Id. 2020 StringTableEntry assetId = StringTable->insert( pAssetId ); 2021 2022 // Reset result count. 2023 S32 resultCount = 0; 2024 2025 // Find depended-on entry. 2026 typeAssetIsDependedOnHash::Iterator dependedOnItr = mAssetIsDependedOn.find( assetId ); 2027 2028 // Iterate all dependencies. 2029 while( dependedOnItr != mAssetIsDependedOn.end() && dependedOnItr->key == assetId ) 2030 { 2031 // Store as result. 2032 pAssetQuery->mAssetList.push_back(dependedOnItr->value); 2033 2034 // Next dependency. 2035 dependedOnItr++; 2036 2037 // Increase result count. 2038 resultCount++; 2039 } 2040 2041 return resultCount; 2042} 2043 2044//----------------------------------------------------------------------------- 2045 2046S32 AssetManager::findInvalidAssetReferences( AssetQuery* pAssetQuery ) 2047{ 2048 // Debug Profiling. 2049 PROFILE_SCOPE(AssetManager_FindInvalidAssetReferences); 2050 2051 // Sanity! 2052 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2053 2054 // Reset result count. 2055 S32 resultCount = 0; 2056 2057 // Iterate referenced assets. 2058 for( typeReferencedAssetsHash::Iterator assetItr = mReferencedAssets.begin(); assetItr != mReferencedAssets.end(); ++assetItr ) 2059 { 2060 // Find asset definition. 2061 AssetDefinition* pAssetDefinition = findAsset( assetItr->key ); 2062 2063 // Skip if the asset definition was found. 2064 if ( pAssetDefinition != NULL ) 2065 continue; 2066 2067 // Store as result. 2068 pAssetQuery->mAssetList.push_back(assetItr->key); 2069 2070 // Increase result count. 2071 resultCount++; 2072 } 2073 2074 return resultCount; 2075} 2076 2077//----------------------------------------------------------------------------- 2078 2079S32 AssetManager::findTaggedAssets( AssetQuery* pAssetQuery, const char* pAssetTagNames, const bool assetQueryAsSource ) 2080{ 2081 // Debug Profiling. 2082 PROFILE_SCOPE(AssetManager_FindTaggedAssets); 2083 2084 // Sanity! 2085 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2086 AssertFatal( pAssetTagNames != NULL, "Cannot use NULL asset tag name(s)." ); 2087 2088 // Do we have an asset tag manifest? 2089 if ( mAssetTagsManifest.isNull() ) 2090 { 2091 // No, so warn. 2092 Con::warnf( "Asset Manager: Cannot find tagged assets as no asset tag manifest is present." ); 2093 return 0; 2094 } 2095 2096 // Reset result count. 2097 S32 resultCount = 0; 2098 2099 const char* pTagSeparators = " ,\t\n"; 2100 2101 // Fetch tag count. 2102 U32 assetTagCount = StringUnit::getUnitCount( pAssetTagNames, pTagSeparators ); 2103 2104 // Fetch asset tags. 2105 Vector<AssetTagsManifest::AssetTag*> assetTags; 2106 for( U32 tagIndex = 0; tagIndex < assetTagCount; ++tagIndex ) 2107 { 2108 // Fetch asset tag name. 2109 const char* pTagName = StringUnit::getUnit( pAssetTagNames, tagIndex, pTagSeparators ); 2110 2111 // Fetch asset tag. 2112 AssetTagsManifest::AssetTag* pAssetTag = mAssetTagsManifest->findAssetTag( pTagName ); 2113 2114 // Did we find the asset tag? 2115 if ( pAssetTag == NULL ) 2116 { 2117 // No, so warn. 2118 Con::warnf( "AssetTagsManifest: Asset Manager: Cannot find tagged assets of '%s' as it does not exist. Ignoring tag.", pTagName ); 2119 continue; 2120 } 2121 2122 assetTags.push_back( pAssetTag ); 2123 } 2124 2125 // Fetch found asset tag count. 2126 assetTagCount = assetTags.size(); 2127 2128 // Did we find any tags? 2129 if ( assetTagCount == 0 ) 2130 { 2131 // No, so warn. 2132 Con::warnf( "AssetTagsManifest: Asset Manager: No specified tagged assets found in '%s'.", pAssetTagNames ); 2133 return 0; 2134 } 2135 2136 // Use asset-query as the source? 2137 if ( assetQueryAsSource ) 2138 { 2139 AssetQuery filteredAssets; 2140 2141 // Yes, so iterate asset query. 2142 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 2143 { 2144 // Fetch asset Id. 2145 StringTableEntry assetId = *assetItr; 2146 2147 // Skip if asset is not valid. 2148 if ( !isDeclaredAsset( assetId ) ) 2149 continue; 2150 2151 // Reset matched flag. 2152 bool assetTagMatched = false; 2153 2154 // Iterate asset tags. 2155 for ( Vector<AssetTagsManifest::AssetTag*>::iterator assetTagItr = assetTags.begin(); assetTagItr != assetTags.end(); ++assetTagItr ) 2156 { 2157 // Fetch asset tag. 2158 AssetTagsManifest::AssetTag* pAssetTag = *assetTagItr; 2159 2160 // Skip if asset is not tagged. 2161 if ( !pAssetTag->containsAsset( assetId ) ) 2162 continue; 2163 2164 // Flag as matched. 2165 assetTagMatched = true; 2166 break; 2167 } 2168 2169 // Did we find a match? 2170 if ( assetTagMatched ) 2171 { 2172 // Yes, so is asset already present? 2173 if ( !filteredAssets.containsAsset( assetId ) ) 2174 { 2175 // No, so store as result. 2176 filteredAssets.mAssetList.push_back(assetId); 2177 2178 // Increase result count. 2179 resultCount++; 2180 } 2181 } 2182 } 2183 2184 // Set asset query. 2185 pAssetQuery->set( filteredAssets ); 2186 } 2187 else 2188 { 2189 // Iterate asset tags. 2190 for ( Vector<AssetTagsManifest::AssetTag*>::iterator assetTagItr = assetTags.begin(); assetTagItr != assetTags.end(); ++assetTagItr ) 2191 { 2192 // Fetch asset tag. 2193 AssetTagsManifest::AssetTag* pAssetTag = *assetTagItr; 2194 2195 // Iterate tagged assets. 2196 for ( Vector<typeAssetId>::iterator assetItr = pAssetTag->mAssets.begin(); assetItr != pAssetTag->mAssets.end(); ++assetItr ) 2197 { 2198 // Fetch asset Id. 2199 StringTableEntry assetId = *assetItr; 2200 2201 // Skip if asset Id is already present. 2202 if ( pAssetQuery->containsAsset( assetId ) ) 2203 continue; 2204 2205 // Store as result. 2206 pAssetQuery->mAssetList.push_back(assetId); 2207 2208 // Increase result count. 2209 resultCount++; 2210 } 2211 } 2212 } 2213 2214 return resultCount; 2215} 2216 2217//----------------------------------------------------------------------------- 2218 2219S32 AssetManager::findAssetLooseFile( AssetQuery* pAssetQuery, const char* pLooseFile, const bool assetQueryAsSource ) 2220{ 2221 // Debug Profiling. 2222 PROFILE_SCOPE(AssetManager_FindAssetLooseFile); 2223 2224 // Sanity! 2225 AssertFatal( pAssetQuery != NULL, "Cannot use NULL asset query." ); 2226 AssertFatal( pLooseFile != NULL, "Cannot use NULL loose file." ); 2227 2228 // Expand loose file. 2229 char looseFileBuffer[1024]; 2230 Con::expandPath(looseFileBuffer, sizeof(looseFileBuffer), pLooseFile, NULL, false ); 2231 2232 // Fetch asset loose file. 2233 StringTableEntry looseFile = StringTable->insert( looseFileBuffer ); 2234 2235 // Reset result count. 2236 S32 resultCount = 0; 2237 2238 // Use asset-query as the source? 2239 if ( assetQueryAsSource ) 2240 { 2241 AssetQuery filteredAssets; 2242 2243 // Yes, so iterate asset query. 2244 for (Vector<StringTableEntry>::iterator assetItr = pAssetQuery->mAssetList.begin(); assetItr != pAssetQuery->mAssetList.end(); ++assetItr) 2245 { 2246 // Fetch asset definition. 2247 AssetDefinition* pAssetDefinition = findAsset( *assetItr ); 2248 2249 // Fetch loose files. 2250 Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles; 2251 2252 // Skip if this asset has no loose files. 2253 if ( assetLooseFiles.size() == 0 ) 2254 continue; 2255 2256 // Search the assets loose files. 2257 for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr ) 2258 { 2259 // Is this the loose file we are searching for? 2260 if ( *looseFileItr != looseFile ) 2261 continue; 2262 2263 // Store as result. 2264 filteredAssets.mAssetList.push_back(pAssetDefinition->mAssetId); 2265 2266 // Increase result count. 2267 resultCount++; 2268 2269 break; 2270 } 2271 } 2272 2273 // Set asset query. 2274 pAssetQuery->set( filteredAssets ); 2275 } 2276 else 2277 { 2278 // No, so iterate declared assets. 2279 for( typeDeclaredAssetsHash::iterator assetItr = mDeclaredAssets.begin(); assetItr != mDeclaredAssets.end(); ++assetItr ) 2280 { 2281 // Fetch asset definition. 2282 AssetDefinition* pAssetDefinition = assetItr->value; 2283 2284 // Fetch loose files. 2285 Vector<StringTableEntry>& assetLooseFiles = pAssetDefinition->mAssetLooseFiles; 2286 2287 // Skip if this asset has no loose files. 2288 if ( assetLooseFiles.size() == 0 ) 2289 continue; 2290 2291 // Search the assets loose files. 2292 for( Vector<StringTableEntry>::iterator looseFileItr = assetLooseFiles.begin(); looseFileItr != assetLooseFiles.end(); ++looseFileItr ) 2293 { 2294 // Is this the loose file we are searching for? 2295 if ( *looseFileItr != looseFile ) 2296 continue; 2297 2298 // Store as result. 2299 pAssetQuery->mAssetList.push_back(pAssetDefinition->mAssetId); 2300 2301 // Increase result count. 2302 resultCount++; 2303 2304 break; 2305 } 2306 } 2307 } 2308 2309 return resultCount; 2310} 2311 2312//----------------------------------------------------------------------------- 2313 2314bool AssetManager::scanDeclaredAssets( const char* pPath, const char* pExtension, const bool recurse, ModuleDefinition* pModuleDefinition ) 2315{ 2316 // Debug Profiling. 2317 PROFILE_SCOPE(AssetManager_ScanDeclaredAssets); 2318 2319 // Sanity! 2320 AssertFatal( pPath != NULL, "Cannot scan declared assets with NULL path." ); 2321 AssertFatal( pExtension != NULL, "Cannot scan declared assets with NULL extension." ); 2322 2323 // Expand path location. 2324 char pathBuffer[1024]; 2325 Con::expandPath( pathBuffer, sizeof(pathBuffer), pPath ); 2326 2327 // Find files. 2328 Vector<Platform::FileInfo> files; 2329 if ( !Platform::dumpPath( pathBuffer, files, recurse ? -1 : 0 ) ) 2330 { 2331 // Failed so warn. 2332 Con::warnf( "Asset Manager: Failed to scan declared assets in directory '%s'.", pathBuffer ); 2333 return false; 2334 } 2335 2336 // Is the asset file-path located within the specified module? 2337 if ( !Con::isBasePath( pathBuffer, pModuleDefinition->getModulePath() ) ) 2338 { 2339 // No, so warn. 2340 Con::warnf( "Asset Manager: Could not add declared asset file '%s' as file does not exist with module path '%s'", 2341 pathBuffer, 2342 pModuleDefinition->getModulePath() ); 2343 return false; 2344 } 2345 2346 // Info. 2347 if ( mEchoInfo ) 2348 { 2349 Con::printSeparator(); 2350 Con::printf( "Asset Manager: Scanning for declared assets in path '%s' for files with extension '%s'...", pathBuffer, pExtension ); 2351 } 2352 2353 // Fetch extension length. 2354 const U32 extensionLength = dStrlen( pExtension ); 2355 2356 // Fetch module assets. 2357 ModuleDefinition::typeModuleAssetsVector& moduleAssets = pModuleDefinition->getModuleAssets(); 2358 2359 TamlAssetDeclaredVisitor assetDeclaredVisitor; 2360 2361 // Iterate files. 2362 for ( Vector<Platform::FileInfo>::iterator fileItr = files.begin(); fileItr != files.end(); ++fileItr ) 2363 { 2364 // Fetch file info. 2365 Platform::FileInfo& fileInfo = *fileItr; 2366 2367 // Fetch filename. 2368 const char* pFilename = fileInfo.pFileName; 2369 2370 // Find filename length. 2371 const U32 filenameLength = dStrlen( pFilename ); 2372 2373 // Skip if extension is longer than filename. 2374 if ( extensionLength > filenameLength ) 2375 continue; 2376 2377 // Skip if extension not found. 2378 if ( dStricmp( pFilename + filenameLength - extensionLength, pExtension ) != 0 ) 2379 continue; 2380 2381 // Clear declared assets. 2382 assetDeclaredVisitor.clear(); 2383 2384 // Format full file-path. 2385 char assetFileBuffer[1024]; 2386 dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", fileInfo.pFullPath, fileInfo.pFileName ); 2387 2388 // Parse the filename. 2389 if ( !mTaml.parse( assetFileBuffer, assetDeclaredVisitor ) ) 2390 { 2391 // Warn. 2392 Con::warnf( "Asset Manager: Failed to parse file containing asset declaration: '%s'.", assetFileBuffer ); 2393 continue; 2394 } 2395 2396 // Fetch asset definition. 2397 AssetDefinition& foundAssetDefinition = assetDeclaredVisitor.getAssetDefinition(); 2398 2399 // Did we get an asset name? 2400 if ( foundAssetDefinition.mAssetName == StringTable->EmptyString() ) 2401 { 2402 // No, so warn. 2403 Con::warnf( "Asset Manager: Parsed file '%s' but did not encounter an asset.", assetFileBuffer ); 2404 continue; 2405 } 2406 2407 // Set module definition. 2408 foundAssetDefinition.mpModuleDefinition = pModuleDefinition; 2409 2410 // Format asset Id. 2411 char assetIdBuffer[1024]; 2412 dSprintf(assetIdBuffer, sizeof(assetIdBuffer), "%s%s%s", 2413 pModuleDefinition->getModuleId(), 2414 ASSET_SCOPE_TOKEN, 2415 foundAssetDefinition.mAssetName ); 2416 2417 // Set asset Id. 2418 foundAssetDefinition.mAssetId = StringTable->insert( assetIdBuffer ); 2419 2420 // Does this asset already exist? 2421 if ( mDeclaredAssets.contains( foundAssetDefinition.mAssetId ) ) 2422 { 2423 // Yes, so warn. 2424 Con::warnf( "Asset Manager: Encountered asset Id '%s' in asset file '%s' but it conflicts with existing asset Id in asset file '%s'.", 2425 foundAssetDefinition.mAssetId, 2426 foundAssetDefinition.mAssetBaseFilePath, 2427 mDeclaredAssets.find( foundAssetDefinition.mAssetId )->value->mAssetBaseFilePath ); 2428 2429 continue; 2430 } 2431 2432 // Create new asset definition. 2433 AssetDefinition* pAssetDefinition = new AssetDefinition( foundAssetDefinition ); 2434 2435 // Store in declared assets. 2436 mDeclaredAssets.insert( pAssetDefinition->mAssetId, pAssetDefinition ); 2437 2438 // Store in module assets. 2439 moduleAssets.push_back( pAssetDefinition ); 2440 2441 // Info. 2442 if ( mEchoInfo ) 2443 { 2444 Con::printSeparator(); 2445 Con::printf( "Asset Manager: Adding Asset Id '%s' of type '%s' in asset file '%s'.", 2446 pAssetDefinition->mAssetId, 2447 pAssetDefinition->mAssetType, 2448 pAssetDefinition->mAssetBaseFilePath ); 2449 } 2450 2451 // Fetch asset Id. 2452 StringTableEntry assetId = pAssetDefinition->mAssetId; 2453 2454 // Fetch asset dependencies. 2455 TamlAssetDeclaredVisitor::typeAssetIdVector& assetDependencies = assetDeclaredVisitor.getAssetDependencies(); 2456 2457 // Are there any asset dependencies? 2458 if ( assetDependencies.size() > 0 ) 2459 { 2460 // Yes, so iterate dependencies. 2461 for( TamlAssetDeclaredVisitor::typeAssetIdVector::iterator assetDependencyItr = assetDependencies.begin(); assetDependencyItr != assetDependencies.end(); ++assetDependencyItr ) 2462 { 2463 // Fetch asset Ids. 2464 StringTableEntry dependencyAssetId = *assetDependencyItr; 2465 2466 // Insert depends-on. 2467 mAssetDependsOn.insertEqual( assetId, dependencyAssetId ); 2468 2469 // Insert is-depended-on. 2470 mAssetIsDependedOn.insertEqual( dependencyAssetId, assetId ); 2471 2472 // Info. 2473 if ( mEchoInfo ) 2474 { 2475 Con::printf( "Asset Manager: Asset Id '%s' has dependency of Asset Id '%s'", assetId, dependencyAssetId ); 2476 } 2477 } 2478 } 2479 2480 // Fetch asset loose files. 2481 TamlAssetDeclaredVisitor::typeLooseFileVector& assetLooseFiles = assetDeclaredVisitor.getAssetLooseFiles(); 2482 2483 // Are there any loose files? 2484 if ( assetLooseFiles.size() > 0 ) 2485 { 2486 // Yes, so iterate loose files. 2487 for( TamlAssetDeclaredVisitor::typeLooseFileVector::iterator assetLooseFileItr = assetLooseFiles.begin(); assetLooseFileItr != assetLooseFiles.end(); ++assetLooseFileItr ) 2488 { 2489 // Fetch loose file. 2490 StringTableEntry looseFile = *assetLooseFileItr; 2491 2492 // Info. 2493 if ( mEchoInfo ) 2494 { 2495 Con::printf( "Asset Manager: Asset Id '%s' has loose file '%s'.", assetId, looseFile ); 2496 } 2497 2498 // Store loose file. 2499 pAssetDefinition->mAssetLooseFiles.push_back( looseFile ); 2500 } 2501 } 2502 } 2503 2504 // Info. 2505 if ( mEchoInfo ) 2506 { 2507 Con::printSeparator(); 2508 Con::printf( "Asset Manager: ... Finished scanning for declared assets in path '%s' for files with extension '%s'.", pathBuffer, pExtension ); 2509 Con::printSeparator(); 2510 Con::printBlankLine(); 2511 } 2512 2513 return true; 2514} 2515 2516//----------------------------------------------------------------------------- 2517 2518bool AssetManager::scanReferencedAssets( const char* pPath, const char* pExtension, const bool recurse ) 2519{ 2520 // Debug Profiling. 2521 PROFILE_SCOPE(AssetManager_ScanReferencedAssets); 2522 2523 // Sanity! 2524 AssertFatal( pPath != NULL, "Cannot scan referenced assets with NULL path." ); 2525 AssertFatal( pExtension != NULL, "Cannot scan referenced assets with NULL extension." ); 2526 2527 // Expand path location. 2528 char pathBuffer[1024]; 2529 Con::expandPath( pathBuffer, sizeof(pathBuffer), pPath ); 2530 2531 // Find files. 2532 Vector<Platform::FileInfo> files; 2533 if ( !Platform::dumpPath( pathBuffer, files, recurse ? -1 : 0 ) ) 2534 { 2535 // Failed so warn. 2536 Con::warnf( "Asset Manager: Failed to scan referenced assets in directory '%s'.", pathBuffer ); 2537 return false; 2538 } 2539 2540 // Info. 2541 if ( mEchoInfo ) 2542 { 2543 Con::printSeparator(); 2544 Con::printf( "Asset Manager: Scanning for referenced assets in path '%s' for files with extension '%s'...", pathBuffer, pExtension ); 2545 } 2546 2547 // Fetch extension length. 2548 const U32 extensionLength = dStrlen( pExtension ); 2549 2550 TamlAssetReferencedVisitor assetReferencedVisitor; 2551 2552 // Iterate files. 2553 for ( Vector<Platform::FileInfo>::iterator fileItr = files.begin(); fileItr != files.end(); ++fileItr ) 2554 { 2555 // Fetch file info. 2556 Platform::FileInfo& fileInfo = *fileItr; 2557 2558 // Fetch filename. 2559 const char* pFilename = fileInfo.pFileName; 2560 2561 // Find filename length. 2562 const U32 filenameLength = dStrlen( pFilename ); 2563 2564 // Skip if extension is longer than filename. 2565 if ( extensionLength > filenameLength ) 2566 continue; 2567 2568 // Skip if extension not found. 2569 if ( dStricmp( pFilename + filenameLength - extensionLength, pExtension ) != 0 ) 2570 continue; 2571 2572 // Clear referenced assets. 2573 assetReferencedVisitor.clear(); 2574 2575 // Format full file-path. 2576 char assetFileBuffer[1024]; 2577 dSprintf( assetFileBuffer, sizeof(assetFileBuffer), "%s/%s", fileInfo.pFullPath, fileInfo.pFileName ); 2578 2579 // Format reference file-path. 2580 typeReferenceFilePath referenceFilePath = StringTable->insert( assetFileBuffer ); 2581 2582 // Parse the filename. 2583 if ( !mTaml.parse( referenceFilePath, assetReferencedVisitor ) ) 2584 { 2585 // Warn. 2586 Con::warnf( "Asset Manager: Failed to parse file containing asset references: '%s'.", referenceFilePath ); 2587 continue; 2588 } 2589 2590 // Fetch usage map. 2591 const TamlAssetReferencedVisitor::typeAssetReferencedHash& assetReferencedMap = assetReferencedVisitor.getAssetReferencedMap(); 2592 2593 // Do we have any asset references? 2594 if ( assetReferencedMap.size() > 0 ) 2595 { 2596 // Info. 2597 if ( mEchoInfo ) 2598 { 2599 Con::printSeparator(); 2600 } 2601 2602 // Iterate usage. 2603 for( TamlAssetReferencedVisitor::typeAssetReferencedHash::const_iterator usageItr = assetReferencedMap.begin(); usageItr != assetReferencedMap.end(); ++usageItr ) 2604 { 2605 // Fetch asset name. 2606 typeAssetId assetId = usageItr->key; 2607 2608 // Info. 2609 if ( mEchoInfo ) 2610 { 2611 Con::printf( "Asset Manager: Found referenced Asset Id '%s' in file '%s'.", assetId, referenceFilePath ); 2612 } 2613 2614 // Add referenced asset. 2615 addReferencedAsset( assetId, referenceFilePath ); 2616 } 2617 } 2618 } 2619 2620 // Info. 2621 if ( mEchoInfo ) 2622 { 2623 Con::printf( "Asset Manager: ... Finished scanning for referenced assets in path '%s' for files with extension '%s'.", pathBuffer, pExtension ); 2624 Con::printSeparator(); 2625 Con::printBlankLine(); 2626 } 2627 2628 return true; 2629} 2630 2631//----------------------------------------------------------------------------- 2632 2633AssetDefinition* AssetManager::findAsset( const char* pAssetId ) 2634{ 2635 // Debug Profiling. 2636 PROFILE_SCOPE(AssetManager_FindAsset); 2637 2638 // Sanity! 2639 AssertFatal( pAssetId != NULL, "Cannot find NULL asset Id." ); 2640 2641 // Fetch asset Id. 2642 StringTableEntry assetId = StringTable->insert( pAssetId ); 2643 2644 // Find declared asset. 2645 typeDeclaredAssetsHash::iterator declaredAssetItr = mDeclaredAssets.find( assetId ); 2646 2647 // Find if we didn't find a declared asset Id. 2648 if ( declaredAssetItr == mDeclaredAssets.end() ) 2649 return NULL; 2650 2651 return declaredAssetItr->value; 2652} 2653 2654//----------------------------------------------------------------------------- 2655 2656void AssetManager::addReferencedAsset( StringTableEntry assetId, StringTableEntry referenceFilePath ) 2657{ 2658 // Debug Profiling. 2659 PROFILE_SCOPE(AssetManager_AddReferencedAsset); 2660 2661 // Sanity! 2662 AssertFatal( assetId != NULL, "Cannot add referenced asset with NULL asset Id." ); 2663 AssertFatal( referenceFilePath != NULL, "Cannot add referenced asset with NULL reference file-path." ); 2664 2665 // Find referenced asset. 2666 typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find( assetId ); 2667 2668 // Did we find the asset? 2669 if ( referencedAssetItr == mReferencedAssets.end() ) 2670 { 2671 // No, so add asset Id. 2672 mReferencedAssets.insertEqual( assetId, referenceFilePath ); 2673 } 2674 else 2675 { 2676 // Yes, so add asset Id with a unique file. 2677 while( true ) 2678 { 2679 // Finish if this file is already present. 2680 if ( referencedAssetItr->value == referenceFilePath ) 2681 return; 2682 2683 // Move to next asset Id. 2684 referencedAssetItr++; 2685 2686 // Is this the end of referenced assets or a different asset Id? 2687 if ( referencedAssetItr == mReferencedAssets.end() || 2688 referencedAssetItr->key != assetId ) 2689 { 2690 // Yes, so add asset reference. 2691 mReferencedAssets.insertEqual( assetId, referenceFilePath ); 2692 return; 2693 } 2694 }; 2695 } 2696} 2697 2698//----------------------------------------------------------------------------- 2699 2700void AssetManager::renameAssetReferences( StringTableEntry assetIdFrom, StringTableEntry assetIdTo ) 2701{ 2702 // Debug Profiling. 2703 PROFILE_SCOPE(AssetManager_RenameAssetReferences); 2704 2705 // Sanity! 2706 AssertFatal( assetIdFrom != NULL, "Cannot rename asset references using NULL asset Id from." ); 2707 AssertFatal( assetIdTo != NULL, "Cannot rename asset references using NULL asset Id to." ); 2708 2709 // Finish if the asset is not referenced. 2710 if ( !mReferencedAssets.count( assetIdFrom ) ) 2711 return; 2712 2713 // Setup referenced update visitor. 2714 TamlAssetReferencedUpdateVisitor assetReferencedUpdateVisitor; 2715 assetReferencedUpdateVisitor.setAssetIdFrom( assetIdFrom ); 2716 assetReferencedUpdateVisitor.setAssetIdTo( assetIdTo ); 2717 2718 // Find first referenced asset Id. 2719 typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find( assetIdFrom ); 2720 2721 // Iterate references. 2722 while( true ) 2723 { 2724 // Finish if end of references. 2725 if ( referencedAssetItr == mReferencedAssets.end() || referencedAssetItr->key != assetIdFrom ) 2726 return; 2727 2728 // Info. 2729 if ( mEchoInfo ) 2730 { 2731 Con::printf( "Asset Manager: Renaming declared Asset Id '%s' to Asset Id '%s'. Updating referenced file '%s'", 2732 assetIdFrom, 2733 assetIdTo, 2734 referencedAssetItr->value ); 2735 } 2736 2737 // Update asset file declaration. 2738 if ( !mTaml.parse( referencedAssetItr->value, assetReferencedUpdateVisitor ) ) 2739 { 2740 // No, so warn. 2741 Con::warnf("Asset Manager: Cannot rename referenced asset Id '%s' to asset Id '%s' as the referenced asset file could not be parsed: %s", 2742 assetIdFrom, assetIdTo, referencedAssetItr->value ); 2743 } 2744 2745 // Move to next reference. 2746 referencedAssetItr++; 2747 } 2748} 2749 2750//----------------------------------------------------------------------------- 2751 2752void AssetManager::removeAssetReferences( StringTableEntry assetId ) 2753{ 2754 // Debug Profiling. 2755 PROFILE_SCOPE(AssetManager_RemoveAssetReferences); 2756 2757 // Sanity! 2758 AssertFatal( assetId != NULL, "Cannot rename asset references using NULL asset Id." ); 2759 2760 // Finish if the asset is not referenced. 2761 if ( !mReferencedAssets.count( assetId ) ) 2762 return; 2763 2764 // Setup referenced update visitor. 2765 TamlAssetReferencedUpdateVisitor assetReferencedUpdateVisitor; 2766 assetReferencedUpdateVisitor.setAssetIdFrom( assetId ); 2767 assetReferencedUpdateVisitor.setAssetIdTo( StringTable->EmptyString() ); 2768 2769 // Find first referenced asset Id. 2770 typeReferencedAssetsHash::Iterator referencedAssetItr = mReferencedAssets.find(assetId); 2771 2772 // Iterate references. 2773 while( true ) 2774 { 2775 // Finish if end of references. 2776 if ( referencedAssetItr == mReferencedAssets.end() || referencedAssetItr->key != assetId ) 2777 break; 2778 2779 // Info. 2780 if ( mEchoInfo ) 2781 { 2782 Con::printf( "Asset Manager: Removing Asset Id '%s' references from file '%s'", 2783 assetId, 2784 referencedAssetItr->value ); 2785 } 2786 2787 // Update asset file declaration. 2788 if ( !mTaml.parse( referencedAssetItr->value, assetReferencedUpdateVisitor ) ) 2789 { 2790 // No, so warn. 2791 Con::warnf("Asset Manager: Cannot remove referenced asset Id '%s' as the referenced asset file could not be parsed: %s", 2792 assetId, 2793 referencedAssetItr->value ); 2794 } 2795 2796 // Move to next reference. 2797 referencedAssetItr++; 2798 } 2799 2800 // Remove asset references. 2801 mReferencedAssets.erase( assetId ); 2802} 2803 2804//----------------------------------------------------------------------------- 2805 2806void AssetManager::renameAssetDependencies( StringTableEntry assetIdFrom, StringTableEntry assetIdTo ) 2807{ 2808 // Debug Profiling. 2809 PROFILE_SCOPE(AssetManager_RenameAssetDependencies); 2810 2811 // Sanity! 2812 AssertFatal( assetIdFrom != NULL, "Cannot rename asset dependencies using NULL asset Id from." ); 2813 AssertFatal( assetIdTo != NULL, "Cannot rename asset dependencies using NULL asset Id to." ); 2814 2815 // Rename via depends-on... 2816 while( mAssetDependsOn.count( assetIdFrom ) > 0 ) 2817 { 2818 // Find depends-on. 2819 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(assetIdFrom); 2820 2821 // Fetch dependency asset Id. 2822 StringTableEntry dependencyAssetId = dependsOnItr->value; 2823 2824 // Find is-depends-on entry. 2825 typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find(dependencyAssetId); 2826 2827 // Sanity! 2828 AssertFatal( isDependedOnItr != mAssetIsDependedOn.end(), "Asset dependencies are corrupt!" ); 2829 2830 while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value != assetIdFrom ) 2831 { 2832 isDependedOnItr++; 2833 } 2834 2835 // Sanity! 2836 AssertFatal( isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value == assetIdFrom, "Asset dependencies are corrupt!" ); 2837 2838 // Remove is-depended-on. 2839 mAssetIsDependedOn.erase( isDependedOnItr ); 2840 2841 // Remove depends-on. 2842 mAssetDependsOn.erase( dependsOnItr ); 2843 2844 // Insert depends-on. 2845 mAssetDependsOn.insertEqual( assetIdTo, dependencyAssetId ); 2846 2847 // Insert is-depended-on. 2848 mAssetIsDependedOn.insertEqual( dependencyAssetId, assetIdTo ); 2849 } 2850 2851 // Rename via is-depended-on... 2852 while( mAssetIsDependedOn.count( assetIdFrom ) > 0 ) 2853 { 2854 // Find is-depended-on. 2855 typeAssetIsDependedOnHash::Iterator isdependedOnItr = mAssetIsDependedOn.find(assetIdFrom); 2856 2857 // Fetch dependency asset Id. 2858 StringTableEntry dependencyAssetId = isdependedOnItr->value; 2859 2860 // Find depends-on entry. 2861 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(dependencyAssetId); 2862 2863 // Sanity! 2864 AssertFatal( dependsOnItr != mAssetDependsOn.end(), "Asset dependencies are corrupt!" ); 2865 2866 while( dependsOnItr != mAssetDependsOn.end() && dependsOnItr->key == dependencyAssetId && dependsOnItr->value != assetIdFrom ) 2867 { 2868 dependsOnItr++; 2869 } 2870 2871 // Sanity! 2872 AssertFatal( dependsOnItr->key == dependencyAssetId && dependsOnItr->value == assetIdFrom, "Asset dependencies are corrupt!" ); 2873 2874 // Remove is-depended-on. 2875 mAssetIsDependedOn.erase( isdependedOnItr ); 2876 2877 // Remove depends-on. 2878 mAssetDependsOn.erase( dependsOnItr ); 2879 2880 // Insert depends-on. 2881 mAssetDependsOn.insertEqual( dependencyAssetId, assetIdTo ); 2882 2883 // Insert is-depended-on. 2884 mAssetIsDependedOn.insertEqual( assetIdTo, dependencyAssetId ); 2885 } 2886} 2887 2888//----------------------------------------------------------------------------- 2889 2890void AssetManager::removeAssetDependencies( const char* pAssetId ) 2891{ 2892 // Debug Profiling. 2893 PROFILE_SCOPE(AssetManager_RemvoeAsetDependencies); 2894 2895 // Sanity! 2896 AssertFatal( pAssetId != NULL, "Cannot remove asset dependencies using NULL asset Id." ); 2897 2898 // Fetch asset Id. 2899 StringTableEntry assetId = StringTable->insert( pAssetId ); 2900 2901 // Remove from depends-on assets. 2902 while( mAssetDependsOn.count( assetId ) > 0 ) 2903 { 2904 // Find depends-on. 2905 typeAssetDependsOnHash::Iterator dependsOnItr = mAssetDependsOn.find(assetId); 2906 2907 // Fetch dependency asset Id. 2908 StringTableEntry dependencyAssetId = dependsOnItr->value; 2909 2910 // Find is-depends-on entry. 2911 typeAssetIsDependedOnHash::Iterator isDependedOnItr = mAssetIsDependedOn.find(dependencyAssetId); 2912 2913 // Sanity! 2914 AssertFatal( isDependedOnItr != mAssetIsDependedOn.end(), "Asset dependencies are corrupt!" ); 2915 2916 while( isDependedOnItr != mAssetIsDependedOn.end() && isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value != assetId ) 2917 { 2918 isDependedOnItr++; 2919 } 2920 2921 // Sanity! 2922 AssertFatal( isDependedOnItr->key == dependencyAssetId && isDependedOnItr->value == assetId, "Asset dependencies are corrupt!" ); 2923 2924 // Remove is-depended-on. 2925 mAssetIsDependedOn.erase( isDependedOnItr ); 2926 2927 // Remove depends-on. 2928 mAssetDependsOn.erase( dependsOnItr ); 2929 } 2930} 2931 2932//----------------------------------------------------------------------------- 2933 2934void AssetManager::unloadAsset( AssetDefinition* pAssetDefinition ) 2935{ 2936 // Debug Profiling. 2937 PROFILE_SCOPE(AssetManager_UnloadAsset); 2938 2939 // Destroy the asset. 2940 pAssetDefinition->mpAssetBase->deleteObject(); 2941 2942 // Increase unloaded count. 2943 pAssetDefinition->mAssetUnloadedCount++; 2944 2945 // Is the asset internal? 2946 if ( pAssetDefinition->mAssetInternal ) 2947 { 2948 // Yes, so decrease internal loaded asset count. 2949 mLoadedInternalAssetsCount--; 2950 } 2951 else 2952 { 2953 // No, so decrease external loaded assets count. 2954 mLoadedExternalAssetsCount--; 2955 } 2956 2957 // Is the asset private? 2958 if ( pAssetDefinition->mAssetPrivate ) 2959 { 2960 // Yes, so decrease private loaded asset count. 2961 mLoadedPrivateAssetsCount--; 2962 2963 // Remove it completely. 2964 removeDeclaredAsset( pAssetDefinition->mAssetId ); 2965 } 2966} 2967 2968//----------------------------------------------------------------------------- 2969 2970void AssetManager::onModulePreLoad( ModuleDefinition* pModuleDefinition ) 2971{ 2972 // Debug Profiling. 2973 PROFILE_SCOPE(AssetManager_OnModulePreLoad); 2974 2975 // Add module declared assets. 2976 addModuleDeclaredAssets( pModuleDefinition ); 2977 2978 // Is an asset tags manifest specified? 2979 if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString() ) 2980 { 2981 // Yes, so load the asset tags manifest. 2982 loadAssetTags( pModuleDefinition ); 2983 } 2984} 2985 2986//----------------------------------------------------------------------------- 2987 2988void AssetManager::onModulePreUnload( ModuleDefinition* pModuleDefinition ) 2989{ 2990 // Debug Profiling. 2991 PROFILE_SCOPE(AssetManager_OnModulePreUnload); 2992 2993 // Is an asset tags manifest specified? 2994 if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString() ) 2995 { 2996 // Yes, so save the asset tags manifest. 2997 saveAssetTags(); 2998 2999 // Do we have an asset tags manifest? 3000 if ( !mAssetTagsManifest.isNull() ) 3001 { 3002 // Yes, so remove it. 3003 mAssetTagsManifest->deleteObject(); 3004 mAssetTagsModuleDefinition = NULL; 3005 } 3006 } 3007} 3008 3009//----------------------------------------------------------------------------- 3010 3011void AssetManager::onModulePostUnload( ModuleDefinition* pModuleDefinition ) 3012{ 3013 // Debug Profiling. 3014 PROFILE_SCOPE(AssetManager_OnModulePostUnload); 3015 3016 // Remove declared assets. 3017 removeDeclaredAssets( pModuleDefinition ); 3018} 3019
